Файл: А. Б. Шнейвайс основы программирования.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.12.2023

Просмотров: 339

Скачиваний: 6

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

4.3
Ещё несколько простых ФОРТРАН примеров.
Рассмотрим задачу суммирования первых n элементов одномерного мас- сива. Оформим алгоритм разными способами:
1. главной программой;
2. внешней функцией;
3. внутренней функцией;
4. воспользуемся встроенной ФОРТРАН-функцией sum.
Для краткости текста главной программы первые n элементов масси- ва заполним числами натурального ряда, вводя только n.
Конечно, указанную сумму можно найти по известной формуле, не проводя суммирование "в лоб". Однако, на тривиальной задаче проще приобрести навыки работы с одномерным массивом, а совпадение результатов, полученных обоими способами, может служить критерием отсутствия ошибок и в записи алгоритма суммирования, и в записи упо- мянутой формулы.
4.3.1
Оформление простой программой program testpsum; implicit none; integer, parameter :: nmax=1000
integer n, i; real ar(nmax), s write(*,*) ’Введи (n<=1000) - число заполняемых элементов массива’
read (*,*) n; write(*,*) ’ n=’,n do i=1,n; ar(i)=i; enddo; write(*,1000) (i,ar(i),i=1,n)
s=0
do i=1,n; s=s+ar(i); enddo
! Современный ФОРТРАН позволяет: s=sum(ar).
write(*,*) ’ s=’,s,’ по формуле:’,n*(n+1.0)/2.0 1000 format(1x,’
Номер
Cодержимое
’/&
&
1x,’ элемента элемента
’/(1x,i5,e20.7) )
end
Введи (n<=1000) - число заполняемых элементов массива ! Результат работы
5
! исполнимого файла n=
5
! программы testpsum
Номер
Cодержимое элемента элемента
1 0.1000000E+01 2
0.2000000E+01 3
0.3000000E+01 4
0.4000000E+01 5
0.5000000E+01
s=
15.00000
по формуле:
15.00000 182

4.3.2
Оформление внешней функцией
В качестве аргументов функции примем имя массива и количество сум- мируемых элементов. Современный ФОРТРАН предоставляет несколько способов описания массива в качестве формального параметра. Исполь- зуем способ явного задания формы и размера массива, служащего фор- мальным параметром.
function fsum1(a,n) result(s); implicit none ! Функция fsum1(a,n) находит integer n, i; real a(n), s
! сумму первых n элементов s=0.0; do i=1,n; s=s+a(i); enddo
! одномерного массива (a).
end function fsum1
program testfsum1; implicit none
! Программа запоминает в первых n integer, parameter :: nmax=1000
! элементах вещественного вектора real ar(nmax), fsum1, s
! ar(nmax) первые n чисел integer n, i
! натурального ряда, а затем вызывает write(*,*) ’Введи (n) - число генерируемых элементов массива’
read (*,*) n; write(*,*) ’ n=’,n
! функцию fsum1(a,n), которая находит do i=1,n; ar(i)=i; enddo
! сумму первых n элементов вектора a.
write(*,1000) (i,ar(i),i=1,n)
s=fsum1(ar,n)
! Обращение к внешней функции fsum1.
write(*,*) ’ n=’,n,’ s=’,s, ’ по формуле:’, n*(n+1.0)/2.0 1000 format(1x,’
Номер
Cодержимое
’/&
&
1x,’ элемента элемента
’/(1x,i5,e20.7) )
end
Введи (n<=1000) - число заполняемых элементов массива ! Результат работы
5
! tstfsum1 совпадает с n=
5
! результатом из 4.3.1.
Номер
Cодержимое элемента элемента
! Заметим, однако, что в tstfsum1 1
0.1000000E+01
! массив ar состоит из 1000 элементов,
2 0.2000000E+01
! а функция fsum1 при обращении
3 0.3000000E+01
! fsum1(аr,n) будет "считать" его
4 0.4000000E+01
! 5-элементным. Ничего страшного
5 0.5000000E+01
! в этом нет. ВАЖНО, чтобы n s=
15.00000
по формуле:
15.00000
! НЕ БЫЛО БОЛЬШЕ 1000.
1. В старых ФОРТРАН-программах описание массива (формального аргумента процедуры), могло иметь вид real a(1).
Не используем подобные описания: некоторые компиляторы
“рассматривают” выход индекса (при работе программы) за объ- явленный диапазон как ошибку.
183


2. Если формальный аргумент – массив, то в качестве фактиче- ского аргумента может быть и элемент массива. Функцию fsum1
без каких-либо изменений можно использовать для подсчёта суммы элементов с любого элемента до n-го:
program tsqfsum1;
! Программа демонстрирует возможность implicit none
! подачи в качестве фактического аргу- integer, parameter :: nmax=1000
! мента не только имени массива, но и real ar(nmax),fsum1, s
!
его элемента, несмотря на то, что integer n, i
!
соответствующий формальный аргумент write(*,*) ’Введи (n) - число генерируемых элементов массива’ ! описан как read (*,*) n; write(*,*) ’ n=’,n
! массив do i=1,n; ar(i)=i; enddo;
write(*,1000) (i,ar(i),i=1,n); s=fsum1(ar,n)
! Передан: массив ar;
write(*,*)’ n=’,n,’ s=’,s,’ по формуле:’,n*(n+1.0)/2.0
s=fsum1(ar(3),n-2)
! элемент ar(3);
write(*,1001) 3,5,s do i=1,n; s=fsum1(ar(i), n-i+1); write(*,1001) i,n,s;enddo ! элемент ar(i).
1000 format(1x,’
Номер
Cодержимое
’/&
&
1x,’ элемента элемента
’/(1x,i5,e20.7))
1001 format(1x,i2,’..’,i2,’: s=’,e15.7)
end
Введи (n) - число генерируемых элементов массива
5
n= 5
Номер
Cодержимое элемента элемента
1 0.1000000E+01 2
0.2000000E+01 3
0.3000000E+01 4
0.4000000E+01 5
0.5000000E+01
n= 5 s=
15. по формуле:
15.
3.. 5: s=
0.1200000E+02
<--= Здесь a(3)+a(4)+a(5)
1.. 5: s=
0.1500000E+02
<--=
a(1)+a(2)+a(3)+a(4)+a(5)
2.. 5: s=
0.1400000E+02
<--=
a(2)+a(3)+a(4)+a(5)
3.. 5: s=
0.1200000E+02
<--=
a(3)+a(4)+a(5)
4.. 5: s=
0.9000000E+01
<--=
a(4)+a(5)
5.. 5: s=
0.5000000E+01
<--=
a(5)
Рекомендация: Подобную возможность ФОРТРАНа (то есть по- дачу в качестве аргумента процедуры имени конкретного элемен- та массива вместо имени самого массива) лучше не использо- вать – она требует от человека особого внимания. Однако в чужих программах указанный прием может встретиться. Поэтому полезно иметь представление о нем.
184

4.3.3
Оформление внутренней ФОРТРАН-функцией
Как и в предыдущем примере в качестве двух формальных аргументов функции выберем имя массива и имя переменной c числом суммируемых элементов.
program tinfsum0; implicit none
! Программа демонстрирует описание integer, parameter :: nmax=1000
! внутренней функции пользователя real ar(nmax), s
!
fsum0(a,n), которая подсчитывает integer n, i
! сумму первых n элементов вектора.
write(*,*) ’Введи (n) - число заполняемых элементов массива’
read (*,*) n; write(*,*) ’ n=’,n ar=(/ (i,i=1,n) /)
! Справа от = конструктор массива write(*,1000) (i,ar(i),i=1,n)
s=fsum0(ar,n)
!<--= Возможные вызовы fsum0
write(*,1002) n, s, n*(n+1)/2.0
s=fsum0(ar(3),n-2); write(*,1001) 3,5,s
!<--=
do i=1,n; s=fsum0(ar(i), n-i+1); write(*,1001) i,n,s; enddo !<--=
1000 format( 1x,’
Номер
Cодержимое
’/&
&
1x,’ элемента элемента
’/ (1x,i5,e20.7) )
1001 format(1x,i2,’..’,i2,’: s=’,e15.7)
1002 format(1x,’ n=’,i2,’ s=’,e15.7,’ по формуле:’,e15.7)
contains
!
function fsum0(a,n) result(s)
!
real a(n), s; integer n, i
! Описание внутренней s=0; do i=1,n; s=s+a(i); enddo
! ! функции.
end function fsum0
!
end
1. Если главная программа при вызове внутренней функции всегда требует сложения всеx элеменов массива до n-го включительно, то имя n можно исключить из списка формальных и фактических ар- гументов: ведь оно глобально по отношению к внутренней функции и потому доступно из неё. После исключения, однако, в функции придётся заменить описание real a(n) на real a(nmax), т.к. имя переменной n без помещения в список формальных аргументов про- цедуры, нельзя использовать для указания размера массива.
2. Расчет суммы элементов вектора выгодно оформить внешней функ- цией – обращение к ней может потребоваться в самых разных про- граммах. Именно поэтому в ФОРТРАН-95 включена соответствую- щая встроенная функция sum, позволяющая удобно и эффектив- но суммировать элементы массива (или его сечения) любой допу- стимой размерности.
185


4.3.4
Чуть-чуть о встроенной ФОРТРАН-функции SUM
Современный ФОРТРАН позволяет вообще не описывать функцию рас- чета суммы элементов вектора, так как имеет свою собственную соот- ветствующую встроенную функцию sum(имя массива). Поэтому на современном ФОРТРАНе должна пройти программа:
program testsum
! Программа запоминает в первых n элементах implicit none
! вещественного вектора ar(nmax) первые n integer nmax, n, i
! чисел натурального ряда, а затем вызывает parameter (nmax=1000)
! встроенную функцию sum, которая посредством real ar(nmax), fsum1, s
! вызова sum(ar(i1:i2)) находит сумму элементов write(*,*) ’Введи (n) - число заполняемых элементов массива’ !
с i1-го .
read (*,*) n; write(*,*) ’ n=’,n
! по i2-ой do i=1,n; ar(i)=i; enddo;
write(*,1000) (i,ar(i),i=1,n);
s=sum(ar(1:n)); write(*,1002) n,s,n,s/n,(n+1)/2.0;
!
вызовы s=sum(ar(3:n)); write(*,*) ’n=’,n-2,’ s=’,s,’ s/n=’,s/(n-2) ! встроенной do i=1, n
!
sum s=sum(ar(i:n))
! и печать write(*,*) ’ n=’,n-i+1,’ s=’,s,’ s/n=’,s/(n-i+1)
! результатов enddo s=sum(ar(3:4)); write(*,*) ’ s=’,s
!<--= еще один вызов sum
1000 format(1x,’
Номер
Cодержимое
’/&
&
1x,’ элемента элемента
’/ (1x,i5,e20.7) )
1002 format(1x,’ n=’,i2,’ s=’,e15.7,’ s/’,i2,’=’,e15.7,&
&
’ по формуле:’,e15.7)
end
1. Вызов встроенной sum более удобен, чем вызов fsum1. Например,
если нужно просуммировать элементы с третьего по четвертый, то вызов fsum1 следует записать так: s=fsum1(ar(3),2). Здесь, хоть и просто, но второй аргумент (двойку) пришлось вычислить в уме.
При вызове же s=sum(ar(3:4)) даже мысли не возникает о целе- сообразности такого подсчета.
2. Наряду с функцией sum современный ФОРТРАН предоставляет целое семейство функций, нацеленных на работу с массивами (см.,
[2, 3, 4] или в данном пособии раздел 7. Эти встроенные функции можно распределить по нескольким подгруппам, например: вычис- лительная работа с массивами (нахождение суммы, произведения элементов, скалярного произведения векторов, максимального или минимального элементов); преобразование массивов (многомерный в одномерный или наоборот); получение справочных данных о мас- сиве (размер, форма, значение границ по каждому измерению).
186

4.4
ФОРТРАН-массив как формальный аргумент функции.
Современный ФОРТРАН предоставляет три способа описания массива в качестве формального аргумента:
1. Явное задание формы формального аргумента.
2. Заимствование формальным аргументом формы фактического.
3. Заимствовании формальным аргументом размера фактического.
4.4.1
Явное задание формы формального аргумента
Явное задание формы формального аргумента позволяет указать про- цедуре, что его ранг и размер, если нужно, могут отличаться от ранга и размера соответствующего фактического аргумента. Вспомним програм- му из пункта 4.3.2, тестирующую внешнюю функцию fsum1:
program testsum; implicit none
! Программа запоминает в первых n integer, parameter :: nmax=1000 ! элементах вещественного вектора real ar(nmax), fsum1, s
! ar(nmax) первые n чисел integer n, i
! натурального ряда, а затем вызывает write(*,*) ’Введи (n) - число заполняемых элементов массива’
read (*,*) n; write(*,*) ’ n=’,n ! функцию fsum1, которая находит do i=1,n; ar(i)=i; enddo
! сумму первых n элементов вектора ar.
write(*,1000) (i,ar(i),i=1,n)
s=fsum1(ar,n); write(*,*) ’ s=’,s
1000 format(1x,’ Номер
Cодержимое
’/(1x,i4,e20.7) )
end function fsum1(a,n) result(s); implicit none ! Функция fsum1(a,n) находит integer n, i; real a(n), s
! сумму первых n элементов s=0.0; do i=1,n; s=s+a(i); enddo
! одномерного массива (a).
end function fsum1 1. В главной программе массив ar состоит из 1000 элементов.
2. В функции fsum1 формальный аргумент – массив a состоит из n элементов. При n=5 функция полагает массив ar пятиэлементным.
3. Описание формального аргумента в виде real a(n) удобно, так как исходный текст функции не зависит от конкретного значения n.
4. Значение n, задаваемое в программе, вызывающей fsum1, не долж- но превышать числа элементов массива, заявленного в програм- ме. Так при вводе n=2000 получим Segmentation fault, а при n=1001 — зацикливание.
187


Иногда выгодно указать процедуре, что ранг её формального аргу- мента (массива) отличается от ранга фактического. Пусть процедура должна найти сумму элементов шестимерного массива. Убедимся, что одномерная индексация выгоднее шестимерной.
Cуммирование шестимерного массива real a(10,10,10,10,10,10) по- ручим функции fsum3 с шестикратным циклом; одномерного — fsum1,
а встроенная sum разберётся с размерностью по умолчанию.
program testsum3; implicit none
! Программа подсчитывает kk integer,parameter :: n=10, n6=n*n*n*n*n*n ! раз (kk вводится) сумму real a (n,n,n,n,n,n) /1000000*1.0/
! миллиона элементов шести- real s1, s2, s3, fsum1, fsum3
! мерного массива, вызывая real t(2), r0, r1, r2, r3; integer k, kk
! 1) fsum1(a,n6), полагающую write(*,*) ’Сколько раз вычислим сумму?’
!
массив (a) одномерным;
read (*,*) kk; write(*,*) ’kk=’, kk
! 2) fsum3(a, n), полагающую call etime(t,r0);
!
массив (a) шестимерным;
do k=1,kk; s1=fsum1(a,n6); enddo;call etime(t,r1) !
3)
встроенную sum(a)
do k=1,kk; s2=fsum3(a,n ); enddo;call etime(t,r2) ! и находит время do k=1,kk; s3=sum(a);
enddo;call etime(t,r3)
!
нужное write(*,1000); write(*,’(a,3(f12.1))’) ’Сумма’,s1, s2, s3
! для расчёта write(*,’(a,3(f12.3))’) ’Время’, r1-r0, r2-r1, r3-r2
! каждому из
1000 format(1x,6x,’fsum1(a,n6)’,2x,’fsum3(a,n)’,3x,’sum(a)’) !
способов.
end function fsum3(a,n) result(s); implicit none ! Функция fsum3(a,n) находит integer n, i1,i2,i3,i4,i5, i6
!
сумму n**6
элементов real a(n,n,n,n,n,n), s
! шестимерного массива (a),
s=0.0; do i1=1,n; do i2=1,n; do i3=1,n
! используя шестикратный цикл.
do i4=1,n; do i5=1,n; do i6=1,n s=s+a(i1,i2,i3,i4,i5,i6)
enddo; enddo; enddo; enddo; enddo; enddo end function fsum3
kk fsum1(a,n6)
fsum3(a,n)
sum(b)
Сумма
1000000.0 1000000.0 1000000.0
Ключ
-O0
-OI
-O0
-O1
-O0
-O1 1
Время
0.015 0.007 0.068 0.052 0.011 0.003 2
Время
0.024 0.010 0.127 0.105 0.021 0.004 10
Время
0.107 0.030 0.645 0.524 0.105 0.024 100
Время
1.027 0.256 6.274 5.208 1.052 0.235
Для ключей оптимизации -O0 и -O1 экономия времени при замене мно- гомерного массива одномерным налицо. Меньше всего времени на работу требуется, естественно, встроенной функции sum; внешней же fsum3,
при работе с шестимерным массивом требуется в 5-6 раз больше време- ни при ключе оптимизации -O0 и практически на порядок больше при ключе оптимизации -O1.
188

4.4.2
Заимствование формы фактического аргумента
Имеется ввиду, что форма массива, служащего формальным аргумен- том заимствуется у фактического. Признак заимствования — после двоеточия не указывается верхняя граница формального параметра.
Выгода: из списка формальных аргументов можно исключить граничные индексы массива (а, значит, и возможную ошибку их пе- редачи при оформлении вызова процедуры).
Внутри процедуры граничные индексы массива (фактического аргу- мента) находим, используя элементные (т.е. способные возвращать в ка- честве результата массив) функции lbound и ubound, получающие гра- ницы измерений массива (нижние и верхние соответственно).
1.
program testsum4; implicit none
! Программа демонстрирует вызов interface function fsum4(a) result(s); real :: a(:), s; end function fsum4
end interface integer,parameter
:: na=1000, nb=2000
! функции fsum4(a) с формальным real a (na), b(nb), sa, sb; integer i
! аргументом - массивом, который do i=1,na; a(i)=i; enddo;
!
по описанию a(:) перенимает do i=1,nb; b(i)=i; enddo;
! форму у фактического аргумента.
sa=fsum4(a); write(*,*) ’
Сумма элементов (a) =’, sa sb=fsum4(b); write(*,*) ’
Сумма элементов (b) =’, sb write(*,*) ’ lbound(a)=’,lbound(a), ’ubound(a)=’,ubound(a)
write(*,*) ’ lbound(b)=’,lbound(b), ’ubound(b)=’,ubound(b)
end function fsum4(a) result(s); implicit none ! Функция fsum4(a) находит сумму integer n1(1), n2(1), i; real :: a(:), s
! элементов одномерного массива n1=lbound(a); n2=ubound(a)
! A, вычисляя граничные индексы write(*,1000) n1(1), n2(1)
! посредством встроенных s=0.0; do i=n1(1),n2(1); s=s+a(i); enddo
! функций lbound и ubound
1000 format(1x,’ n1(1)=’,i5, ’
n2(1)=’,i5,$)
end
Описание a(:) удобно, если нижний индекс фактического аргумента равен 1, иначе lbound и ubound получат индексы массива лишь согласованного с фактическим, начав индексацию с 1.
При использовании процедур с аргументами-массивами перенимаю- щими форму наличие явного интерфейса необходимо, в то время как, например, testsum3 обходилась по старинке неявным.
В современном ФОРТРАНе целесообразно в том или ином виде ВСЕГДА указывать интерфейс процедур.
189


2. Для заимствования формы массива и его индексации при нижней границе фактического аргумента отличной от единицы используем конструкцию имя_массива ( нижний_индекс : ).
program testsum5; implicit none interface function fsum5(x) result(s); real s; real, dimension (-3:) :: x end function fsum5
endinterface real a(-3:10),
b(-3:5), c(-3:0),
d(-3:-1)
real sa
, sb
, sc
, sd integer i write(*,100) ’
main: lbound(a) =’, lbound(a), ’ ubound(a)=’, ubound(a)
write(*,100) ’
lbound(b) =’, lbound(b), ’ ubound(b)=’, ubound(b)
write(*,100) ’
lbound(c) =’, lbound(c), ’ ubound(c)=’, ubound(c)
write(*,100) ’
lbound(d) =’, lbound(d), ’ ubound(d)=’, ubound(d)
a(-3:10)=(/ (i,i=-3,10) /)
! Инициализация b(-3: 5)=(/ (i,i=-3, 5) /)
!
векторов c(-3: 0)=(/ (i,i=-3, 0) /)
!
посредством d(-3:-1)=(/ (i,i=-3,-1) /)
!
конструктора массива sa=fsum5(a); sb=fsum5(b); sc=fsum5(c); sd=fsum5(d)
write(*,*) ’ sa=’,sa,’ sb=’,sb,’ sc=’,sc,’ sd=’,sd
100 format(a,i3,a,i3)
end program testsum5
function fsum5(x) result(s)
! Функция fsum5(x), находя сумму элементов implicit none
! массива (x), заимствующего у фактического integer i
! аргумента с индексом начального элемента real x(-3:), s
! равным -3 ФОРМУ, для проверки правильности integer n1(1), n2(1)
! заимствования индексации выводит принятые n1=lbound(x);
! значения нижней и верхней границ n2=ubound(x)
write(*,*) ’ fsum5: lbound(x) =’,lbound(x),’ ubound(x) =’,ubound(x)
s=0.0
do i=n1(1), n2(1); s=s+x(i); enddo end function fsum5
main: lbound(a) = -3 ubound(a)= 10
!
Результат пропуска исполнимого кода,
lbound(b) = -3 ubound(b)=
5
!
полученного на gfortran из lbound(c) = -3 ubound(c)=
0
!
gcc version 4.5.0
lbound(d) = -3 ubound(d)= -1
fsum5: lbound(x) =
-3
ubound(x) =
10
fsum5: lbound(x) =
-3
ubound(x) =
5
fsum5: lbound(x) =
-3
ubound(x) =
0
fsum5: lbound(x) =
-3
ubound(x) =
-1
sa=
49.000000
sb=
9.0000000
sc=
-6.0000000
sd=
-6.0000000 190

3. Если индексация фактического аргумента отличается от индексации соответствующего формального, то в программе, которая вызывает процедуру, необходимо сообщать явный интерфейс процедуры.
Без наличия явного интерфейса процедуры fsum6 (при замене ин- дексации формального аргумента c x(-3:) на x(-2:)) получаем:
program testsum6; implicit none; integer i real a(-3:10), b(-3:5), c(-3:0), d(-3:-1), sa, sb, sc, sd write(*,100) ’
main: lbound(a) =’, lbound(a), ’ ubound(a)=’, ubound(a)
write(*,100) ’
lbound(b) =’, lbound(b), ’ ubound(b)=’, ubound(b)
write(*,100) ’
lbound(c) =’, lbound(c), ’ ubound(c)=’, ubound(c)
write(*,100) ’
lbound(d) =’, lbound(d), ’ ubound(d)=’, ubound(d)
a(-3:10)=(/ (i,i=-3,10) /);
c(-3: 0)=(/ (i,i=-3, 0) /)
b(-3: 5)=(/ (i,i=-3, 5) /);
d(-3:-1)=(/ (i,i=-3,-1) /)
sa=fsum6(a); sb=fsum6(b); sc=fsum6(c); sd=fsum6(d)
write(*,*) ’ sa=’,sa,’ sb=’,sb,’ sc=’,sc,’ sd=’,sd
100 format(a,i3,a,i3)
end program testsum6
function fsum6(x) result(s) ! Функция fsum6(x) воспринимает фактический implicit none;
! аргумент, от которого формальный заимствует integer i
! ФОРМУ, индексированным не от -3, как указано real x(-2:), s
! в главной программе, а от -2).
integer n1(1), n2(1)
! При отсутствии в последней явного описания n1=lbound(x)
! интерфейса вызов ubound внутри функции n2=ubound(x)
! завершается аварийно.
write(*,*) ’ fsum6: lbound(x) =’, lbound(x),’ ubound(x) =’, ubound(x)
s=0.0; do i=n1(1), n2(1);
s=s+x(i); enddo end function fsum6
gfortran tstfsum6.f95 fsum6.f95
# Компиляция завершится с кодом 0.
./a.out
# Но запуск исполнимого кода main: lbound(a) = -3 ubound(a)= 10
# при вызове ubound завершится lbound(b) = -3 ubound(b)=
5
# аварийно lbound(c) = -3 ubound(c)=
0
lbound(d) = -3 ubound(d)= -1
fsum5: lbound(x) =
-2
ubound(x) =
8388606
Ошибка сегментирования main: lbound(a) = -3 ubound(a)= 10
#
Результат пропуска исполнимого lbound(b) = -3 ubound(b)=
5
#
кода после указания явного lbound(c) = -3 ubound(c)=
0
#
интерфейса lbound(d) = -3 ubound(d)= -1
fsum5: lbound(x) =
-2
ubound(x) =
11
fsum5: lbound(x) =
-2
ubound(x) =
6
fsum5: lbound(x) =
-2
ubound(x) =
1
fsum5: lbound(x) =
-2
ubound(x) =
0
sa= 49.000000
sb= 9.0000000
sc= -6.0000000
sd= -6.0000000 191