Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КОНСПЕКТ 2.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
241.66 Кб
Скачать

Построение циклов при помощи условных операторов

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

Рассмотрим задачу, которая упоминается в биографии великого немецкого математика XIX века Фридриха Гаусса. В начальный класс, в котором учился Гаусс, пришел учитель и задал достаточно сложную для детей задачу: сложить все числа от 1 до 100. Учитель рассчитывал немного отдохнуть, в ожидании ответа, но Гаусс назвал ответ мгновенно: 5050!

Читателю предоставляется самостоятельно догадаться до метода решения задачи, придуманного маленьким Гауссом, а мы решим задачу тем методом, который предполагал учитель, т.е. путем последовательного сложения всех чисел. Естественно, что мы не будем складывать числа вручную, а поручим это компьютеру. Простейший способ решения задачи будет иметь вид:

x=1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+

20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+

37+38+39+40+41+42+43+44+45+46+47+48+49+50+51+52+53+

54+55+56+57+58+59+60+61+62+63+64+65+66+67+68+69+70+

71+72+73+74+75+76+77+78+79+80+81+82+83+84+85+86+87+

88+89+90+91+92+93+94+95+96+97+98+99+100;

Такой способ вряд ли заслуживает поощрения. Главное не столько в его громоздкости, сколько в том, что он не допускает обобщения на другое количество чисел. Возможно требование, чтобы считать сумму всех чисел не от 1 до 100, а от 1 до произвольного числа N, значение которого заранее не известно и выясняется только в процессе работы программы. Или еще более общий случай, когда требуется вычислить сумму всех чисел от N1 до N2. Последняя задача решается при помощи следующей программы на С++:

С++

sum=0;

x=N1;

a: sum=sum+x;

x=x+1;

if (x<=N2) goto a;

Рассмотрим подробнее программу на С++. Главным здесь является рекурсивный оператор: sum=sum+x;. Значение суммы sum инициализируется нулем в первом операторе: sum=0;. Затем величина х получает свое начальное значение N1 и это значение прибавляется к sum, после чего величина sum становится равной N1. Затем х увеличивается на единицу, т.е. становится равным N1+1 и выполняется сверка нового значения х с конечным значением N2. Если х не превосходит N2, то условный оператор возвращает вычисления на оператор: sum=sum+x и все повторяется сначала. Цикл прекращается при условии X>N2.

Разумеется, такая программа требует большей квалификации для своего понимания, чем предыдущая, но зато она является по настоящему универсальной, т.е. пригодной для любых значений N1 и N2.

Некоторым недостатком предложенных программ является использование оператора goto, но в данном случае этот недостаток малосущественен. У программ есть другой, более существенный, недостаток, незаметный на первый взгляд. Предположим, что в результате предыдущих вычислений окажется, что N1>N2. В этом случае суммирование теряет смысл. Однако задача в целом может сохранить свою актуальность. Чаще всего, в подобных случаях, следует считать, что искомая сумма равна нулю, поскольку не существует значений х, находящихся в промежутке между N1 и N2.

Однако прежний вариант программ при N1>N2 выдаст значение суммы, равное N1. Это связано с тем, что суммирование sum=sum+x производится до первой проверки в условном операторе; поэтому хотя бы один раз оно выполнится при любых значениях N1 и N2.

Чтобы избежать этого, нужно проверку поставить в начале цикла, а не в конце его. Соответствующая программа будет:

С++

sum=0;

x=N1;

b: if (x>N2) goto a;

sum+=x;

x++;

goto b;

a:

Теперь при N1>N2 цикл заканчивается, не начавшись, и значение суммы остается равным нулю, что и требуется по условию задачи.

Обратим внимание на то, что в программе на С++ мы использовали типичные для этого языка операции: sum+=x; и x++;.

В рассмотренных только что примерах вычисления производились над целыми числами, в связи с чем можно заранее посчитать, сколько раз будут выполняться повторные вычисления в цикле. Однако возможны случаи, когда количество повторений цикла заранее предсказать невозможно или, по крайней мере, очень сложно и лучше выяснять это в процессе работы программы. Чаще всего такие проблемы возникают при суммировании рядов. Известно, что в математическом смысле ряд имеет бесконечное число слагаемых, но компьютер, естественно, может сложить только конечное количество слагаемых. Сложение прекращается тогда, когда слагаемые становятся настолько малыми, что ими можно уже пренебречь.

Рассмотрим, например, бесконечную геометрическую прогрессию:

y=1+x+x2+x3+…

При |x|<1 эта бесконечная сумма дает конечный результат, равный:

Попробуем выполнять суммирование непосредственно. Это достигается при помощи программ:

С++

sum=1;

y=x;

a:sum+=y;

y*=x;

if (fabs(y)>=1e-17)

goto a;

В этой программе применены некоторые характерные приемы, опирающиеся на использование рекурсии. Рассмотрим их подробнее. Обратим главное внимание на то, как вычисляются последовательно возрастающие степени х. Для обозначения произвольной такой степени введена специальная переменная y. Перед началом цикла ей присваивается значение, равное х. После каждой операции суммирования у и sum происходит умножение предыдущего значения у на х. После первого такого умножения величина у становится равной х2, после второго – х3 и т.д. При помощи описанного приема мы получаем последовательные степени х наиболее естественным и экономным образом.

В программе на С++ мы вновь использовали характерные для С++ операции: sum+=y; и y*=x;.

Обратим также внимание на то, что при сравнении в условном операторе учитывается не сама величина у, а ее модуль. Это позволяет использовать не только положительные, но и отрицательные значения х. При этом в С++ для вычисления модуля используется функция fabs.

Проверка на выход из цикла, осуществляемая в конце цикла, вновь может привести к лишним действиям. Например, при х=0 цикл можно не выполнять, поскольку значение суммы заранее известно и равно единице. Хотя в данном случае «лишнее» выполнение цикла и не приводит к ошибкам, приведем тексты программ, в которых проверка стоит в начале цикла, что избавляет от этого «лишнего» выполнения:

С++

sum=1;

y=x;

b:if (fabs(y)<=1e-17)

goto a;

sum+=y;

y*=x;

goto b;

a:

Мы рассмотрели простейшие виды циклов и запрограммировали их при помощи условного оператора и оператора goto. Такое программирование циклов в современном программировании не применяется; здесь оно использовано в учебных целях для того, чтобы лучше понять устройство операторов цикла, рассмотренных ниже.