Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Алгоритмизация и программирование на языке С++. Ч.1. Учебник
.pdf
7. Циклы
cout.setf(ios::xed);
cout.precision(3);
Рис. 7.11. Сумма пяти членов хi / (i!) для х = 2
91
Рис. 7.12. Сумма пяти членов хi / (i!) для х = 0,5
Изменим задачу, чтобы узнать, на каком шаге член сум-
мы станет меньше 0,01.
Используем для решения этой задачи циклы
while
.
do-while
cout.setf(ios::xed);
cout.precision(3);
double dS, x, da, p, q;
int i, n =5;
x =0.2; dS=0.0;p =1.0;q =1.0;
i = 1;
do
{
и

92
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
da = (double)i;
p =p * x; q =q * da;
dS =dS + p/q;
cout << " da (p/q) S " << da << " "
<< (p/q) << " " << dS << endl;
i = i +1;
} while ((p / q) > 0.01) ;
cout << "\n " << dS << endl;
Результат представлен на рис. 7.13.
Рис. 7.13. Сумма членов хi / (i!), вычисляемых пока
их значение больше 0,01
Теперь приведем фрагмент с
while
int i, n=5; double da;
double x =0.2, dS=0.0, p =1.0, q =1.0;
i = 0;
cout.setf(ios::xed);
cout.precision(3);
bool indicator = true;
while ((p / q) > 0.01)
{
i = i + 1;
da = (double)i;
p =p * x; q =q * da;
dS =dS + p/q;
cout << " da (p/q) S " << da << " "
.

7. Циклы
( )
3 5 21
... ( 1) ...
3! 5! 2 1 !
i
i
xx x
Sx
i
+
= − + − +− +
+
35
8 32
2.
3! 5! 6 120
xx
x − + =−+
93
<< (p/q) << " " << dS << endl; // Перенос оператора
i = i +1;
if ((p / q) < 0.02) indicator = false;
}
cout << "\n " << dS << endl;
Результат выполнения такой программы будет таким же.
Выражение для получения очередного члена последовательности из предыдущего (или предыдущих) называется ре-
куррентной формулой. Мы уже использовали это для вычисления факториала, степени.
Рассмотрим задачу вычисления суммы бесконечного функционального ряда
Для трех членов при х = 2 получим
Заметим, что при бесконечном числе членов эта сумма равна функции sin(x).
//x – аргумент функции
//dS – накапливаемая сумма
//c – степени (-1)
//px – числитель
//z – знаменатель
double px, z, dS, x;
int c, f;
x = 2.0; dS = 0.0;
int L; L = 5;
cout << "L= " << L;
for (int l = 1; l < L; l++)
{ f = 1;
for (int i = 1; i <= 2 * l -1; i++)

94
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
{ f = f * i; }
c = pow(–1.0, l); // c^(-l)
px = pow(x, (2 * l -1)); // px=x^(2l+1)
z = f*1.0; // z=(2l+1)!
cout << "l px z === " << l << " "
<< px << " " << z << endl;
dS = dS + c * px/ z;
cout << "c c*px/z dS " << c << " " << (c*px/z)
<< " " << dS << endl;
}
cout.setf(ios::xed);
cout.precision(3);
cout << endl << " S " << dS << " sin(x) " << sin(x) << endl;
Результат представлен на рис. 7.14.
Рис. 7.14. Вычисление функции sin(x) не эффективным
алгоритмом
Теперь приведем эффективную программу, в которой используется рекуррентное соотношение. Введем вспомогательные переменные, в которых будут накапливаться значения
элементов слагаемых. В них будут рекуррентно формировать-
i
ся значения (–1)
– в переменной с, x
и (2i + 1)! – в переменной
z
.
(2i+1)
– в переменной px
Для вычисления степеней (–1) переменная с умножается
с=1
на (–1) на каждом шаге цикла. Начальное значение
присваивается до входа в цикл. И далее переменная с будет получать чередующиеся значения (–1), (+1) и т.д.

7. Циклы
95
Переменная рх должна получать значения, равные числителю – нечетные степени х. До цикла она получает значение
х, а далее на каждом шаге умножается на х два раза.
z
Знаменатель содержится в переменной
. Она должна хра-
нить факториалы нечетных значений натурального ряда (1,
1 ⋅ 2 ⋅ 3, 1 ⋅ 2 ⋅ 3 ⋅ 4 ⋅ 5 и т.д.). Для этого сначала присвоим ей
значение 1 (факториал нуля), а далее будем умножать на (2 ⋅ l)
и (2 ⋅ l + 1). Для l = 1 это 2 и 3, для l = 2 это 4 и 5.
Сначала присвоим этим переменным начальные значения
c=1; px=x; z=1;
Для получения очередного слагаемого запишем такое выражение:
a=c*px/z; S=S+a;
А для подготовки следующих значений используем рекуррентные соотношения:
c=c*(-1); px=px*x*x; z=z*(2*i)*(2*i+1)
Обратим внимание на то, что все эти преобразования переменных (
с, px, z
) производятся после вычисления очередного значения суммы. А до цикла им присваиваются начальные
значения, обеспечивающие добавление к сумме первого чле-
a
. В программе переменная L отвечает за количество слага-
на –
емых. В программе вычисляется значение синуса для х = π/3.
double px, z, dS, x;
int c; int L; L= 5;
x = 3.14159/3.0; dS = x;
c = 1; px=x; z=1;
cout << "L= " << L;
// int start = clock();
// cout << " Start " << start << endl;
cout<<" x= " << x << endl;
for (int l = 1; l < L; l++)
{
cout << "l px z === " << l << " " << px << " " << z;
cout << " 2l = " << (2*l) << " 2l+1 = " << (2*l+1) << endl;
cout << " c c*px/z " << c << " " <<
(c * px/z) << " S= " << dS << endl;

96
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
c=-c; px=px*x*x;
z = z*(2*l)*(2*l+1);
dS = dS + c * px / z;
}
// int nish = clock();
// cout << endl << " Finish " << nish << endl;
cout.setf(ios::xed);
cout.precision(12);
cout << endl << " S " << dS << " sin(x) " << sin(x) << endl;
Результат представлен на рис. 7.15.
Рис. 7.15. Вычисление значения функции sin(x)
с использованием рекуррентных соотношений (L = 5)
Из результатов видно, что сумма отличается от значения,
вычисленного с помощью функции, с шестого знака после
запятой. Если вычислять сумму десяти слагаемых, то получим более точный результат (рис. 7.16).
Как видно, совпадает уже 15 знаков.
Можно не использовать вспомогательные переменные (
), а добавлять к сумме переменную, которая на каждом
px, x
c,
шаге рекуррентно изменяется так:
= a
a
i
·(–1) ⋅ x ⋅ x / ((2i) ⋅ (2i + 1)).
i–1

7. Циклы
Рис. 7.16. Вычисление значения функции sin(x)
с использованием рекуррентных соотношений (L = 10)
97
Для получения этого соотношения нужно записать формулы для i-го и для (i + 1)-го слагаемого, а затем поделить
второе на первое.
Вот так будет выглядеть программа, в которой использовано это соотношение. Для проверки приведенного соотношения оставлены инструкции, вычисляющие три элемента слагаемого.
double px, z, dS, x, da; int c;
int L; L= 5;
x = 3.14159/3.0; dS = x; da=x;
c = 1; px=x; z=1;
cout << "L= " << L;
cout.setf(ios::xed);
cout.precision(6);
cout<<" x= " << x << endl;
for (int l = 1; l < L; l++)
{
c=-c; px=px*x*x;
z = z*(2*l)*(2*l+1);
cout << "c*px/z " << (c * px/z) << " S= " << dS << endl;
da=da*(-1)*x*x/( (2*l)*(2*l+1) );
cout << "da === " << da << endl;
dS = dS + da;
}
cout.setf(ios::xed);
cout.precision(15);
cout << endl << " S " << dS << " sin(x) " << sin(x) << endl;

98
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
Результат приведен на рис. 7.17.
Рис. 7.17. Вычисление значения функции sin(x)
с использованием комплексного рекуррентного соотношения
(L = 5)
Ранее рассматривалась инструкция
выполнение множественного выбора
струкция, влияющая на выполнение циклов. Это
break
, прекращающая
switch
. Есть еще одна ин-
continue
. Она
прерывает не весь цикл, а лишь текущую итерацию. При этом
не выполняются действия в теле цикла, расположенные после
break
нее. А
прерывает выполнение цикла и передает управление на следующую после цикла инструкцию. Приведем пример.
setlocale(LC_ALL,"Russian");
int i=0;
cout << " continue :" << endl;
for( ; i<4; i++)
{
cout << " До оператора continue (for)" << endl;
continue;
cout << "После оператора continue – не выводиться" << endl;
}
i=0;

7. Циклы
99
cout << endl << " break:" << endl;
for( ; i<4; i++)
{
cout << " До оператора break (for)" << endl;
break;
cout << "После оператора break – не выводиться" << endl;
}
i=0;
cout << endl << " continue:" << endl;
do
{
cout << " До оператора comtinue (do)" << endl;
i++;
continue;
cout << "После оператора break – не выводиться" << endl;
} while ( i<4 );
i=0;
cout << endl << " break:" << endl;
do
{
cout << " До оператора break (do)" << endl;
i++;
break;
cout << "После оператора break – не выводиться" << endl;
} while ( i<4 );
Результат приведен на рис. 7.18.
Приведем текст программы, в которой в инструкции множественного выбора используются разные операторы, изменяющие последовательность выполнения программы. Интересно, как работают инструкции
continue
и
return
в
switch
Первый приведет к следующей итерации, а второй прекра-
i=4
щает инструкцию. Таким образом, итерация для
не вы-
полнена.
Похожий фрагмент описан в книге [2].
.

100
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
Рис. 7.18. Операторы
continue
и
for(int i=0; i<=4; i++)
{ cout << "\n i " << i <<endl;
switch (i) { // осторожно
case0:
case 0:
cout << "case 0\n";
continue;
case 1:
cout << "case 1\n";
break;
case 2:
cout << "case 2\n";
goto case0;
case 3:
cout << "case 2\n";
return 3;
default:
cout << "default: case не найден\n";
}
}
break
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
