Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие2013_09_28.doc
Скачиваний:
24
Добавлен:
20.05.2015
Размер:
2.72 Mб
Скачать

8. Итерационные циклы

Итерационнымитрадиционно называют циклы, в которых коли­чес­тво повторений тела цикла заранее неизвестно и цикл завершается обычно по достижении нужной точности вычислений. При этом обычно вычисления ведутся по одной и той же формуле вида

,

когда полученное на предыдущем шаге значение используется на последующем шаге.

Покажем на примерах наиболее существенные моменты, связанные с итерационными циклами.

Задача 51. Вычислить приближенно, с заданной точностью = 0.001 значение функции y = (a > 0) без привлечения библиотечной функции sqrt().

Для решения задачи воспользуемся итерационной формулой Ньютона:

yn+1 = 0.5 ( yn + ) = yn + 0.5 ( yn) , n = 0, 1, 2,…

Эта формула позволяет вычислять очередной член последовательности {yn} через уже вычисленный предыдущий член, начиная с некоторого начального приближения y0 > 0. Можно, например, принять y0= . В математике доказано, что такая последовательность сходится к точному значению . Поскольку мы не можем позволить себе ( да и не надо, наверное ) строить бесконечную последовательность приближений y0 , y1 , . . , yn , . . . , то процесс обрывается при некотором n таким образом, чтобы погрешность вычисления y = не превышала заданной величины > 0. Будем считать, что требуемая точность достигнута, если

yn+1yn  

Из итерационной формулы Ньютона следует, что предыдущее условие можно записать в следующей эквивалентной форме:

yn+1yn = 0.5|yn |  

С учетом всего вышесказанного соответствующая программа может иметь такой вид:

#include <math.h>

#include <stdio.h>

#include <conio.h>

int main()

{

double a, y, y0, v, eps=0.0001;

m1:

printf("введи a > 0 "); scanf("%lf",&a);

if(a <= 0) goto m1;

y0=a/2; y=y0;

do

{

v = 0.5*(a/y - y);

y = y + v;

}

while(fabs(v)>eps);

printf("По итерационной формуле корень из %8.2lf = %lf\n",a, y);

printf("По стандартной функции sqrt(%8.2lf) = %lf\n",a, sqrt(a));

getch(); return 0;

}

По итерационной схеме вычисляют многие элементарные функции, ис­поль­зуя их разложение в степенные ряды (ряды Тейлора–Маклорена), например:

ex = 1 + + + … + + … (1)

cos x = 1 – + – … +(–1)n + … (2)

sin x = x – + – … +(–1)n + … (3)

arctg x = x – + – … +(–1)n +… (x<1) (4)

ln(1+x) = x – + – … +(–1)n–1 + … (x<1) (5)

При вычислении с помощью степенных рядов удобно пользоваться рекуррентными соотношениями, которые позволяют вычислять очередное слагаемое не непосредственно (это было бы слишком примитивно), а через уже вычисленное предыдущее слагаемое. Прямое вычисление очередного слагаемого может привести к непредсказуемым результатам: при возведении в степень и вычислении факториала можно получить очень большие числа; при делении таких чисел друг на друга произойдет потеря точности, так как количество значащих цифр, хранимых в ячейке памяти, ограничено.

Для приведенных выше рядов рекуррентные соотношения могут быть выведены непосредственно: достаточно взять отношение двух соседних слагаемых. Например, для разложения функции ex, общий член ряда которой равен un = , получим:

= = , n=0,1,2,3… (6)

или:

un+1 = un .

Последнее соотношение уже удобно использовать для вычисления значений очередных слагаемых через предыдущие.

И ещё одно замечание. При вычислениях с помощью степенных рядов мы ограничиваемся конечным числом слагаемых, заменяя сумму ряда его частичной суммой

Sn= S0 + S1 + S2 +… +Sn-1 ,

Sn+1 = Sn + un+1 , n = 0,1,2,3… (7)

Для сходящегося ряда модуль unпри увеличении n стремится к нулю. Возникает практический вопрос: сколько членов ряда нужно сохранить, чтобы получившаяся погрешность вычислений не превышала заданную? Для знакопеременных рядов ответ на поставленный вопрос даёт т. н. правило Лейбница: при замене суммы ряда его частичной суммой Sn имеет место погрешность, не превышающая по модулю величины первого из отброшенных слагаемых. Таким образом, вы­чис­ле­ние приближённого значения функции с заданной точностью  можно прекратить, если

un+1   (8)

Воспользуемся этими рассуждениями, чтобы вычислить приближённое значение функции y = sin x, предполагая, что x<2. (Этого всегда можно добиться, используя формулы приведения). Формула (3) может быть запрограммирована в виде итерационного процесса, который описывается следующими рекуррентными соотношениями.

un+1 = un ,

Sn+1 = Sn + un+1 .

Момент окончания вычислений наступит при un+1  .

Задача 52. Вычислить приближённо, с точностью= 0.0001 зна­че­ние функцииy = Sinx, используя описанный выше итерационный процесс. Результат сравнить со значением, полученным с помощью стандартной функцииsin(x).

#include<conio.h>

#include<iostream>

#include <math.h>

using namespace std;

#define eps 0.0001

void main ()

{

int n;

double x,s,u;

printf("введи x\n");

scanf("%lf",&x);

//cin>>x;

printf("%f %lf\n", x ,x);

u=x;s=u;

n=0;

while(fabs(u)>eps)

{

u=-(u*x*x)/(2*n+2)/(2*n+3);

s+=u;n++;

}

printf("Вычисленное значение Sin(%lf):\n",x);

printf("А) По итерационной формуле - %lf\n",s);

printf("Б) По стандартной функции - %lf\n",sin(x));

getch();

}