- •Институт математики, экономики и механики кафедра математического обеспечения компьютерных систем в. С. Макогон, и. Н. Лисицына
- •Оглавление
- •Введение
- •Основныетипы данных, операции и выражения
- •Описание переменных.
- •Операции , выражения и операторы.
- •3. Операторы управления программой. Базовые управляющие структуры.
- •Операторы ветвления Условный оператор if
- •Оператор - переключатель
- •Операторы повторения (цикла).
- •4. Программирование алгоритмов линейной структуры.
- •5. Программирование разветвляющихся алгоритмов (оператор if).
- •6. Программирование разветвляющихся алгоритмов (оператор switch)
- •Оператор for
- •Цикл с постусловием do -while
- •8. Итерационные циклы
- •Задачи для самостоятельного решения
- •9. Программирование алгоритмов с использованием функций
- •Основные понятия численного решения уравнений
- •10. Программирование алгоритмов с использованием массивов
- •11. Символьные переменные и строки. Обработка строк.
- •Другие средства ввода-вывода символов и строк
- •Массивы строк
- •12. Указатели
- •Массивы указателей
- •2. Описание метода трапеций
- •3. Программный комплекс
- •13. Структуры
- •Указатели на структуры
- •14. Файлы. Потоковый ввод-вывод
- •Функции для работы с файлами
- •Открытие файловых потоков
- •Закрытие файловых потоков
- •Удаление файлов
- •Переименование файлов
- •Реинициализация
- •Функции для ввода-вывода по символам
- •1 Вариант) содержит только буквы исходной строки
- •2 Вариант) перевернута по отношению к исходной
- •Двоичные (бинарные) файлы. Блочно-ориентированный ввод-вывод.
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+1 – yn
Из итерационной формулы Ньютона следует, что предыдущее условие можно записать в следующей эквивалентной форме:
yn+1 – yn = 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();
}