Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Алгоритмизация и программирование на языке С++. Ч.1. Учебник

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]