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

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

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

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

Добавлен: 06.12.2023

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

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

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

2.6
Время работы рекурсивной и нерекурсивной функций.
Проведем некоторое сравнение временных затрат при работе рекурсив- ной и нерекурсивной функций, фиксируя моменты начала и завершения n-кратного обращения к ним. Рассмотрим некоторые примеры.
2.6.1
Расчет факториала (временные замеры для СИ).
#include
//
Файл timefact.c
#include
double factorn(int); double factorr(int);
int main()
{ double fn, fr, t01,t12,t23,t34; long int n=10000000, i,k, t0,t1,t2,t3,t4;
printf("число нерекурсивных вызовов (n)=%ld\n",n);
printf("введи аргумент факториала:\n");
scanf("%d",&k); printf(" k=%d\n",k);
t0=clock(); fn=factorn(k);
t1=clock(); fr=factorr(k);
t2=clock(); for (i=1;i<=n;i++) fn=factorn(k);
t3=clock(); for (i=1;i<=n;i++) fr=factorr(k);
t4=clock();
t01=((double)(t1-t0))/CLOCKS_PER_SEC; t12=((double)(t2-t1))/CLOCKS_PER_SEC;
t23=((double)(t3-t2))/CLOCKS_PER_SEC; t34=((double)(t4-t3))/CLOCKS_PER_SEC;
printf("
Нерекурсивная
Рекурсивная \n");
printf("Результат
%15.7le
%15.7le\n",fn,fr);
printf("Время 1 вызова %15.7le
%15.7le\n", t01, t12);
printf("Время n вызова %15.7le
%15.7le\n", t23, t34); return 0; }
double factorn(long int n)
//
Файл factor.c
{ long int i; double p;
// Нерекурсивная функция расчета n!
p=1; for (i=1;i<=n;i++) p*=i;
// Находит n! посредством оператора return p; }
// цикла.
double factorr(long int n)
// Рекурсивная функция расчета n!
{ if (n==0) return 1; else return n*factorr(n-1); }
$ gcc timefact.c factor.c -O0
// ...................... -O1
$ time ./a.out
// $ time ./a.out число нерекурсивных вызовов (n)=10000000
// Замеры при оптимизации -O1
введи аргумент факториала:
//
10
//
Нерекурсивная
Рекурсивная
// Нерекурсивная
Рекурсивная
Результат
3.6288000e+06 3.6288000e+06
Время 1 вызова
0.0000000e+00 0.0000000e+00
Время n вызова
4.6000000e-01 8.4000000e-01
// 2.4000000e-01 2.7000000e-01
real
0m6.520s
//
real
0m2.192s user
0m1.294s
//
user
0m0.517s sys
0m0.004s
//
sys
0m0.001s
69

2.6.2
Расчет факториала (временные замеры для gfortran).
program timefact;
implicit none
!
Файл timefact.f95
integer(8) :: n=10000000, i, k
!...................
real*8 fn, fr; real artime(2), t0,t1,t2,t3,t4, t01,t12,t23,t34
interface real(8) function factorn(n); integer(8) n; end function factorn;
recursive real*8 function factorr(n) result(w); integer(8) n end function factorr end interface write(*,*) ’число нерекурсивных вызовов (n)=’,n write(*,*) ’введи аргумент факториала:’; read (*,*) k;
call etime(artime,t0); fn=factorn(k); call etime(artime,t1)
fr=factorr(k); call etime(artime,t2)
do i=1,n; fn=factorn(k); enddo;
call etime(artime,t3)
do i=1,n; fr=factorr(k); enddo;
call etime(artime,t4)
t01=t1-t0; t12=t2-t1; t23=t3-t1; t34=t4-t3;
write(*,1000); write(*,1001) fn, fr;
write(*,1002) t01, t12; write(*,1003) t23, t34 1000 format(17x,’ Нерекурсивная
Рекурсивная’)
1001 format(1x,’Результат’,6x,e15.7,3x,e15.7)
1002 format(1x,’Время 1 вызова ’,e15.7,3x,e15.7)
1003 format(1x,’Время n вызова ’,e15.7,3x,e15.7)
end program timefact function factorn(n); implicit none
!
Файл factor.f95
real(8) factorn, p; integer(8) n, i
!.......................
p=1; do i=1,n; p=p*i; enddo; factorn=p end function factorn recursive real(8) function factorr(n) result(w); implicit none integer(8) n if (n.eq.0) then;
w=1; else;
w=n*factorr(n-1); endif end function factorr gfortran timefact.f95 factor.f95 -O0
// ....................... -O1
time ./a.out
// time ./a.out число нерекурсивных вызовов (n)=10000000
//
Замеры при оптимизации -O1
введи аргумент факториала:
//
10
//
Нерекурсивная
Рекурсивная
Результат
0.3628800E+07 0.3628800E+07
Время 1 вызова
0.4999805E-05 0.1000008E-05
Время n вызова
0.4760330E+00 0.8589249E+00 // 0.2355780E+00 0.3363059E+00
real
0m2.876s
// real
0m2.536s user
0m1.336s
// user
0m0.572s sys
0m0.002s
// sys
0m0.002s
Как видно, gfortran-программа чуть-чуть уступает gcc-программе.
70


2.6.3
C++ расчет n-го числа Фибоначчи
Последовательность Фибоначчи — числовая последовательность, у кото- рой первые два элемента равны единице, а каждый последующий равен сумме двух предыдущих:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, · · ·
Записи алгоритма расчета n-го числа Фибоначчи и в нерекурсивной, и рекурсивной формах достаточно просты:
int fibon(int n)
//
Файл fibo.cpp
{int i, f1, f2, f3;
// с описанием fibon, fibor1 и fibor2
f1=1; f2=1; f3=1;
for (i=2;ireturn f3;
}
int fibor1(int n) { if (n<3) return 1;
else { return fibor1(n-1)+fibor1(n-2);}
}
int fibor2(int k, int n, int fk1, int fk)
{ if (k==n) return fk; else
{ return fibor2(k+1,n,fk, fk+fk1);} }
fibor1 осуществляет при работе два рекурсивных вызова, причём каж- дый будет многократно рекурсивно перевычислять числа Фибоначчи,
вычисляемые ранее, так как любое из них (после его учёта при расчёте текущего) не запоминается в памяти (кроме последнего).
fibor2 получает конечный результат за счёт одного рекурсивного вызова,
так как запоминает предыдущее число в качестве аргумента fk1.
#include
int fibon(int); int fibor1(int); int fibor2(int,int,int,int);
using namespace std;
int main()
{int krep=10000000, i, n, fn, fr1, fr2, t1,t2,t3,t4;
double t12, t23, t34;
cout<<" Число нерекурсивных вызовов (krep)="<cout<<"введите n:"<>n; cout<<" n="<for (i=1;i<=krep;i++) fn=fibon(n);
t2=clock();
for (i=1;i<=krep;i++) fr1=fibor1(n);
t3=clock();
for (i=1;i<=krep;i++) fr2=fibor2(1,n,0,1);
t4=clock();
cout<<"Функция fibon
"<<"fibor1
"<<"fibor2"<cout<<"Значение "<< fn <<"
"<< fr1<<"
"<t12=double(t2-t1)/CLOCKS_PER_SEC;
t23=double(t3-t2)/CLOCKS_PER_SEC;
t34=double(t4-t3)/CLOCKS_PER_SEC;
cout<<"Время "<"<"<return 0;
}
71

Ниже даны фрагменты вывода приведённой выше программы при клю- чах оптимизации -O0 (слева) и -O1 (справа).
g++ tstfibo.cpp fibo.cpp -c -O0
// g++ tstfibo.cpp -c -O1
./a.out
// ./a.out n=11
//
Функция fibon fibor1
fibor2
//
Функция fibon fibor1
fibor2
Значение
89 89 89
//
Время
0.44 12.58 0.53
//
Время
0.12 8.25 0.21
Работу функции fibor2 можно ускорить. Назовём её модифицирован- ный вариант fibor3):
int fibor3(int n, int f[100])
{ int t;
if ( (n==1) || (n==2) ) { f[n]=1; return 1; }
if (f[n]) return f[n];
else {t=fibor3(n-1,f)+fibor3(n-2,f); f[n]=t; return t;}
}
fibor3 (в отличие от fibor2 запоминает не два последовательных числа
Фибоначчи, а все ранее вычисленные в соответствующих элементах её
второго аргумента — массива, который состоит из достаточного коли- чества элементов. Число Фибоначчи, найденное посредством сложения двух предыдущих при рекурсивном вызове, записывается в элемент мас- сива, так что, когда оно потребуется в последующих рекурсиях, то его можно просто извлечь из этого элемента. Перед вызовом fibor3 массив следует проинициализировать нулями.
Вообще, для n-го числа Фибоначчи известно и явное выражение:
F
n
=
1 +

5 2
!
n

1 −

5 2
!
n

5
Кажется, что по этой простой формуле можно без всякой рекурсии очень быстро вычислить n-ое число Фибоначчи. Это обманчивое впечатление.
double fibof(int n)
{ const double x=(1.0+sqrt(5.0))*0.5; const double y=(1.0-sqrt(5.0))*0.5;
return ( pow(x,(double)n)-pow(y,(double)n) )/sqrt(5.0);
}
Нерекурсивная fibof требует для расчёта 10-го числа Фибоначчи го- раздо больше времени чем fibon, fibor2 или fibor3 72


#include
#include
#define sec(x,y)
((double)((y)-(x)))/CLOCKS_PER_SEC
using namespace std;
int fibon(int); int fibor1(int); int fibor2(int, int, int, int);
int fibor3(int, int []);
double fibonf(int);
int main()
{int krep=10000000, i, n, fn, fr1, fr2, fr3, t1,t2,t3,t4,t5,t6;
double t12, t23, t34, t45, t56,ff;
int work[100];
for (i=0;i<=100;i++)
work[i]=0;
cout<<" Число нерекурсивных вызовов (krep)="<cout<<"введите n:"<>n; cout<<" n="<t1=clock(); for (i=1;i<=krep;i++)
fn=fibon(n);
t2=clock(); for (i=1;i<=krep;i++) fr1=fibor1(n);
t3=clock(); for (i=1;i<=krep;i++) fr2=fibor2(1,n,0,1);
t4=clock(); for (i=1;i<=krep;i++) fr3=fibor3(n,work);
t5=clock(); for (i=1;i<=krep;i++)
ff=fibonf(n);
t6=clock();
cout<<"Функция fibon
"<<"fibor1
"<<"fibor2
"<<"fibo3
"
<<"fibonf
"<< endl;
cout<<"Значение "<< fn <<"
"<< fr1<<"
"
<"<< fr3<<"
"<t12=sec(t1,t2);
t23=sec(t2,t3); t34=sec(t3,t4); t45=sec(t4,t5);
t56=sec(t5,t6);
cout<<"Время "<"<"<"
"<"<return 0;
}
Число нерекурсивных вызовов (krep)=10000000
// Сводная таблица
Функция fibon fibor1
fibor2
fibor3
fiborf // временных затрат n=10
Время
0.53 7.75 0.79 0.12 3.89
// последней n=20
Время
1.18 1072.86 1.82 0.12 3.90
// программы.
Вывод:
При выборе рекурсивной формы записи функции полезно по- думать об экономии времени(сравните времена fibor1 и fibor2).
Вопрос:
“Почему рекурсивная fibor3 гораздо быстрее нерекурсивной fibon?”
73

2.6.4
ФОРТРАН-расчет n-го числа Фибоначчи.
ФОРТРАН-функции, аналогичные СИ-функциям из пункта 2.6.3:
function fibon(n) result(f3)
! Нерекурсивная ФОРТРАН-функция implicit none
! расчета n-го числа Фибоначчи integer f1, f2, f3,
n, i
! через последовательное сложение f1=1d0; f2=1d0; f3=1d0
! каждых двух предыдущих чисел do i=3,n
! (ФОРТРАН-аналог С-функции fibon).
f3=f1+f2; f1=f2; f2=f3
enddo end recursive integer function fibor1(n) result(w)
! Рекурсивный implicit none
! ФОРТРАН-аналог integer n
! С-функции if (n<3) then;
w=1
!
fibor1.
else;
w=fibor1(n-1)+fibor1(n-2)
endif end recursive integer function fibor2(k,n,fk1,fk) result(w) ! Рекурсивный implicit none
! ФОРТРАН-аналог integer n, k;
integer fk1, fk
! С-функции if (k.eq.n) then; w=fk
!
fibor2.
else; w=fibor2(k+1,n,fk, fk+fk1)
endif end recursive integer function fibor3(n,f) result(w)
! Рекурсивный implicit none; integer n
! ФОРТРАН-аналог integer f(100)
! С-функции if ((n.eq.1).or.(n.eq.2)) then; f(n)=1; w=1; endif !
fibor3.
if (f(n).ne.0) then w=f(n)
else f(n)=fibor3(n-1,f)+fibor3(n-2,f)
w=f(n)
endif end real(8) function fibof(n) result(w)
! Нерекурсивная ФОРТРАН-функция implicit none
! расчета n-го числа Фибоначчи integer n
! по формуле, выражающей его real(8), parameter :: c5=sqrt(5d0)
! зависимость от номера числа real(8), parameter :: x=(1d0+c5)*0.5d0;! (ФОРТРАН-аналог real(8), parameter :: y=(1d0-c5)*0.5d0;!
С-функции fibof).
w=(x**n-y**n)/c5
end
Тестирующая программа для подсчёта времени использует встроенную функцию second (см. Приложение III):
74
program tstfibo4; implicit none; integer, parameter :: krep=10000000
integer i, n, fn, fr1, fr2, fr3, fk1, fk, j real t1,t2,t3,t4,t5,t6, t12, t23, t34, t45, t56; real*8 ff integer work(100);
interface; integer function fibon(n); integer n;
end function fibon recursive integer function fibor1(n) result(w); integer n; end function fibor1
recursive integer function fibor2(k,n,fk1,fk) result(w)
integer k, n, fk1, fk;
end function fibor2
recursive integer function fibor3(n,f) result(w);
integer n;
integer f(100);
end function fibor3
real(8) function fibof(n); integer n;
end function fibof end interface work=0;
write(*,*) ’ Число нерекурсивных вызовов (krep)=’, krep write(*,*) ’ введите n:’; read(*,*) n; write(*,*) ’ n=’,n call second(t1);
do i=1,krep;
fn=fibon(n);
enddo call second(t2);
do i=1,krep;
fr1=fibor1(n);
enddo fk1=0d0; fk=1d0
call second(t3);
do i=1,krep;
fr2=fibor2(1,n,fk1,fk); enddo call second(t4);
do i=1,krep;
fr3=fibor3(n,work);
enddo call second(t5);
do i=1,krep;
ff=fibof(n);
enddo call second(t6);
write(*,1000); write(*,1001) fn, fr1, fr2, fr3, ff t12=t2-t1;
t23=t3-t2; t34=t4-t3; t45=t5-t4; t56=t6-t5
write(*,1002) t12, t23, t34, t45, t56 1000 format( 1x,’Функция’,5x,’fibon’,7x,’fibor1’,7x,’fibor2’,&
7x,’fibor3’,7x,’fiborf’)
1001 format(1x,’Значение’,i10,2x,i10,2x,i10,2x,i10,6x,e11.4)
1002 format(1x,’Время’,3x,e11.4,2x,e11.4,2x,e11.4,2x,e11.4,2x,e11.4)
end
Таблица сравнения временных затрат g++ и gfortran:
Число нерекурсивных вызовов (krep)=10000000.
Оптимизация -O0
Функция fibon fibor1
fibor2
fibo3
fiborf n=10
Время
0.53 7.75 0.79 0.12 3.89
g++
Время
0.60 8.42 0.95 0.12 1.250
gfortran n=20
Время
1.18 1072.86 1.82 0.12 3.90
g++
Время
1.38 1103.
2.24 0.12 1.35
gfortran
Функция fibon fibor1
fibor2
fibo3
fiborf
Оптимизация -O1
n=10
Время
0.17 7.82 0.71 0.09 3.39
g++
Время
0.18 8.14 0.97 0.09 0.98
gfortran n=20
Время
0.36 1023.
1.82 0.08 3.65
g++
Время
0.38 1044.
2.26 0.09 1.08
gfortran
Компилятор gfortran в режиме O0 слегка уступает компилятору g++
при работе с данными типа integer; при работе с одномерным массивом вообще не уступает, а с данными типа real(8) (см. колонку fibof) опера- ция возведения в степень gfortranа работает чуть ли не втрое быстрее.
75


2.6.5
Поиск корня методом дихотомии (ФОРТРАН)
Среди численных методов поиска изолированного на промежутке [a,b]
корня уравнения f(x)=0 наиболее надежным (но не слишком быстрым)
является метод деления пополам отрезка, содержащего корень. Суть ме- тода в сужении этого отрезка вдвое до тех пор, пока не получим искомый корень с требуемой точностью (см. приложение bisec).
! Процедура bisecn0(aa,bb,epsx,epsy,res,iter,ier) находит методом деления
! отрезка [aa,bb] пополам изолированный на нём корень уравнения f(x)=0.
! Входные аргументы: aa - левая граница промежутка;
bb - правая граница;
!
epsx - точность по аргументу; epsy - точность по функции.
! Выходные аргументы: res - найденная величина корня;
!
k
- число уточнений, за которое достигнуты требуемые критерии точности;
!
ier - код причины завершения работы bisecn0:
!
0
- достигнуты критерии точности и по функции, и по аргументу;
!
1
- число дроблений отрезка > kmax=32000 (но точность не достигнута);
!
2
- корень не искался, т.к. f(aa) и f(bb) одного знака (нет корня).
subroutine bisecn0(aa,bb,epsx,epsy,res,k,ier); implicit none real(8) aa, bb, epsx, epsy, res, f, a, b, c, fa, fb, fc integer k, ier, kmax / 1000 /; a=aa; b=bb; fa=f(a); fb=f(b)
if ( (fa*fb).le.0d0 ) then
! Если f(x) перескает ось абсцисс, то:
k=0
! Обнуляем число сужений промежутка.
do; c=(a+b)*0.5d0; fc=f(c) ! Находим середину промежутка (с) и f(c).
if ( fa*fc.gt.0d0) then
!
Если корень в правой половине отрезка,
a=c; fa=fc;
else
!
смещаем левую границу b=c; fb=fc
!
если в левой - смещаем правую.
endif
!
k=k+1
!
Увеличиваем счетчик сужений if ((k.gt.kmax).or.&
! Если число сужений больше допустимого
&
(dabs(b-a).lt.epsx.and.&
! ИЛИ одновременно достигнуты точности
&
dabs(fc ).lt.epsy)) exit ! и по аргументу и по функции, то enddo
! выходим из цикла.
res=(a+b)*0.5d0
! Фиксируем найденное значение корня.
if (k.le.kmax) then; ier=0 ! Если число сужений в норме, то код = 0
else; ier=1 !
иначе код завершения = 1
endif else; ier=2
! Если f(x) НЕ ПЕРЕСЕКАЕТ ось абсцисс, код = 2
endif end subroutine bisecn0
Здесь пересылки a=aa и b=bb обеспечивают неизменность исходных значений aa и bb. Пересылки были бы излишни, если бы ФОРТРАН до- пускал передачу параметров по значению. Обойтись без пересылок мож- но, если при вызове bisecn0 заключить фактические аргументы (a) и
(b) в круглые скобки.
76

В рекурсивной форме алгоритм выглядит еще проще:
! Рекурсивная подпрограмма bisecr0(aa,bb,epsx,epsy,res,iter,ier) находит
! методом деления отрезка [aa,bb] пополам изолированный на нем корень
! уравнения f(x)=0.
! Входные аргументы: aa - левая граница промежутка;
bb - правая граница;
!
epsx - точность по аргументу;
epsy - точность по функции;
! Выходные аргументы: res - найденная величина корня;
!
k
- число рекурсий, за которое достигнуты требуемые критерии точности;
! ier - код причины завершения работы bisecr0:
!
0
- достигнуты критерии точности и по функции, и по аргументу;
!
1
- число дроблений отрезка [a,b] > kmax=1000, но точностные
!
критерии либо не достигнуты, либо достигнут лишь один из них;
!
2
- корень не искался, так как на концах промежутка [aa,bb]
!
функция f(x) имеет значения одного знака.
recursive subroutine bisecr0(a,b,epsx,epsy,res,k,ier);
implicit none real(8) aa, bb, epsx, epsy, res, f, a, b, c, fa, fb, fc integer k, ier, kmax / 1000 /
!
a=aa;
b=bb;
fa=f(a);
fb=f(b)
if ( (fa*fb).le.0d0 ) then

1   2   3   4   5   6   7   8   9   ...   23

! Пересекает ли f(x) ось абсцисс?
res=(a+b)*0.5d0; c=res; fc=f(c)
! Да! Находим середину if ( (dabs(b-a).lt.epsx) .and.&
! Если выполнены точностные
&
(dabs( fc).lt.epsy) ) then; ier=0 ! критерии, то ier=0
else if (k.gt.kmax) then; ier=1
! Если число уточнений > kmax, то ier=1
else; c=(a+b)*0.5d0; fc=f(c) ! В противном случае продолжаем k=k+1;
! уточнения.
if (f(a)*fc.gt.0) then call bisecr0(c,b,epsx,epsy,res,k,ier)
else; call bisecr0(a,c,epsx,epsy,res,k,ier)
endif endif endif else; ier=2 ! f(x) не пересекает ось абсцисс.
endif end subroutine bisecr0
В качестве пробного примера выберем решение уравнения 3*x-1=0.
! Подпрограмма-функция f(x) для заданного аргумента x вычисляет значение
! левой части уравнения 3*x-1=0.
function f(x) result(w)
implicit none real(8) w, x w=3*x-1
end
77

Программа, тестирующая процедуры bisecn0 и bisecr0, вводит из фай- ла input текущей директории: границы отрезка [aa,bb] и абсолютные погрешности поиска корня по абсциссе и ординате (epsx и epsy соот- ветственно). Для оценки времени работы каждая из процедур вызыва- ется krep=1000 раз. Ниже приводится текст тестирующей программы и сводная табличка некоторых результатов.
! Программа предназначена для тестирования двух подпрограмм поиска
! изолированного корня уравнения f(x)=0 методом деления отрезка пополам:
!
1) нерекурсивной bisecn(aa,bb,epsx,epsy,res,iter,ier)
!
2) рекурсивной bisecr(aa,bb,epsx,epsy,res,iter,ier)
program tstbis; implicit none real(8) f, aa, bb, epsx, epsy, resn, resr; real t1, t2, t3, t4
character(8) mess(2) /’bisecn0’,’bisecr0’/
integer itern, iterr, iern, ierr, i integer ninp / 5 /,
nres / 6 /, krep / 1000000 /
open (unit=ninp,file=’input’)
open (unit=nres,file=’result’,status=’replace’)
read (ninp, ’(d15.7)’) aa, bb, epsx, epsy write(nres,1100) aa, bb, epsx, epsy, krep call second(t1); do i=1,krep call bisecn0(aa,bb,epsx,epsy,resn,itern,iern)
enddo; call second(t2);
write(nres,1101) resn, f(resn), itern, iern, t2-t1, mess(1)
call second(t3); do i=1,krep; iterr=0
call bisecr0(aa,bb,epsx,epsy,resr,iterr,ierr)
enddo;
call second(t4)
write(nres,1101) resr, f(resr), iterr, ierr, t4-t3, mess(2); close(nres)
1100 format(1x,’
a=’,d15.7,’
b=’,d15.7/ 1x,’epsx=’,d15.7,&
&
’ epsy=’,d15.7,’
krep=’,i10/13x,’res’,14x,’f(res)’,3x,’iter’,3x,’ier’,&
&
3x,’Время’,3x,’Подпрограмма’)
1101 format(1x,d25.17,2x,d9.2,2x,i5,2x,i2,2x,f7.3,6x,a)
end a=
0.0000000D+00
b=
0.1000000D+01
krep=1000
res f(res)
iter ier
Время
Подпрограмма epsx epsy
0.33333206176757812D+00
-0.38D-05 17 0
0.002
bisecn0 1d-5 1d-5 0.33333206176757812D+00
-0.38D-05 17 0
0.005
bisecr0 0.33333333333333337D+00 0.11D-15 32001 1
3.148
bisecn0 1d-25 1d-4 0.33333333333333337D+00 0.11D-15 32001 1
10.948
bisecr0 0.33333333333333337D+00 0.11D-15 1001 1
0.102
bisecn0 1d-5 1d-18 0.33333333333333337D+00 0.11D-15 1001 1
0.319
bisecr0 0.33333333333333348D+00 0.44D-15 50 0
0.005
bisecn0 1d-15 1d-15 0.33333333333333348D+00 0.44D-15 50 0
0.015
bisecr0 78

2.6.6
Поиск корня методом дихотомии (C++)
Ниже приводятся соответствующие задаче исходные С++ тексты: тести- рующей программы, функции расчета левой части решаемого уравнения,
нерекурсивной и рекурсивной функций, реализующих метод деления от- резка пополам, а также результаты пропуска с оценкой временных за- трат g++- и gfortran-исполнимых кодов (без оптимизации), решающих уравнение 3*x-1=0 миллион раз.
#include
// Файл tstbis.cpp
#include
// ===============
#include
#define sec(x,y)
((double)((y)-(x)))/CLOCKS_PER_SEC
using namespace std;
double f(double);
void bisecn0(double,double,double,double,double&,int&,int&);
void bisecr0(double,double,double,double,double&,int&,int&);
int main()
{double a, b, epsx, epsy, resn, resr; int t1, t2, t3, t4;
char* mess[2]={"bisecn0","bisecr0"};
int itern, iterr, iern, ierr, i, krep=1000000;
ifstream ninp ("cinput"); if (!ninp) { cout<<"Файл input НЕ ОТКРЫТ !!!"<return 1;}
ofstream nres("result"); if (!nres){ cout<<"Файл result НЕ ОТКРЫТ !!!"<return 2;}
ninp >> a >> b >> epsx >> epsy; ninp.close();
nres <nres << "
a=" <<
a
<< "
b=" <<
b
<< "
krep=" << krep << endl;
nres << " epsx="<< epsx << " epsy=" << epsy << endl;
nres << "
res
"<<"
f(res)
"<< "
k
"
<< " ier "<< "
Время "<<" Функция "<t1=clock(); for (i=1;i<=krep;i++)
{ bisecn0(a,b,epsx,epsy,resn,itern,iern);}
t2=clock(); nres<"<<<"
"<"<"
<<<"
"<t3=clock(); for (i=1;i<=krep;i++)
{ iterr=0; bisecr0(a,b,epsx,epsy,resr,iterr,ierr); }
t4=clock(); nres<"<<<"
"<"<"
<<< "
"<nres.close();
}
double f(double x) {return 3*x-1;}
79