В простых примерах, рассмотренных выше, вообще говоря, не требовалось привлечения программирования. Все они легко могли быть решены вручную или с помощью калькулятора. Сила ЭВМ заключается в возможности простыми средствами осуществлять многократное повторение заданных действий – циклов.
Итерационные циклы. В случае, если число циклов, необходимых для решения задачи, заранее неизвестно, такие циклы называются итерационными. Рассмотрим ряд примеров.
Задача 5-1.Пусть для некоторого множества чисел Х нужно вычислить и отпечатать функцию Х/2. Ввод и вычисления следует прекратить после обнаружения первого Х, равного нулю. Очевидна следующая блок-схема (рис.5-1а). Блоков ввода, вычисления, печати и анализа столько, сколько чисел в последовательности до первого нуля. Чисел может быть очень много и подобный подход, конечно, неприемлем, не говоря уже о том, что количество их заранее неизвестно. Такие программы строятся по-иному. Обрабатывающая часть программы записывается только раз, но охватывается петлей возврата (рис.5-1б). Тогда одни и те же операторы будут выполняться многократно до тех пор, пока Х#0. Для реализации цикла здесь понадобилась метка (m).
Задание.Наберите программу Р3. Затем улучшите ее: введите необходимые подсказки, отформатируйте вывод, сделайте очистку экрана, введите подсчет количества точек Х, для которых был вычислен Y. Выдайте сообщение “Х=0” по завершении программы.
Задача 5-2. Пусть для аргумента Х, находящегося в диапазоне 3÷9, требуется вычислить и напечатать значение функции Y=(X–6)2, где Х изменяется с шагом 2 (рис. 5-2а, 5-2б). Справа от текста программы сделаны выкладки по проверке решения. В каждой строке вручную вычисляется значение соответствующей переменной. Проверка выполняются сверху-вниз, слева-направо по ходу исполнения программы. Стрелки показывают связи между циклами. Видим, что заданная последовательность изменения Х (3,5,7,...) наблюдается и последнее значение Y вычисляется для Х=9. При следующем приращении Х оно становится равным 11 и пятый цикл не выполняется, поскольку Х>9. Программа завершается. Следует отметить, что нет никакого технически простого способа проверки правильности написанных программ. Для этой цели программисту приходится вручную по тексту программы рассчитывать значения переменных и сличать их с желаемыми (известными из условия). Конечно, проверка выполняется не для всей задачи, а только для небольшого числа (например, 3-х) начальных циклов и при этом тщательно анализируется значение условия выхода из цикла (здесь оператор IF).
Задание. Вычислите функцию в обратном порядке. Подсчитайте среднее арифметическое всех Х и Y.
Арифметические циклы. Если число повторений известно заранее – такие циклы называются арифметическими.
Задача 5-3. Пусть в условиях предыдущей задачи не известно предельное значение аргумента, но зато задано количество точек аргумента – 4. Поскольку в данном случае не задано последнее значение Х, признак окончания циклов придется формировать самим. Для этого вводится переменная, которая фиксирует число уже выполненных циклов, т.е. счетчик циклов (назовем ее I). В исходном состоянии (рис.5-3) берем его равным 1. После выполнения очередного цикла счетчик получает приращение на единицу (I=I+1). В начале каждого цикла в операторе IF делается проверка на достижение счетчиком последнего разрешенного значения (у нас 4). Если I<=4 программа продолжает вычисление функции, если нет (I>4) – счет прекращается. Рядом с программой приведены выкладки по ее проверке. Как видим, результат проверки совпал с результатом, полученным ранее. По очевидным причинам счетчик циклов I должен быть целочисленного типа.
Задание. Напишите программу вычисления функции в обратном порядке. Сделайте число точек не константой (4), а переменной N, вводимой оператором read. При прогоне программы задайте N=100. Поскольку весь результат теперь не умещается на экране, организуйте паузу при выдаче каждых 20-ти строк (понадобится операция mod и readkey).
program P5_3;
проверка
label d;
var x,y:real; i:integer;
begin
цикл
цикл
цикл
цикл
x:=3; i:=1;
d: if i>4 then exit;
y:=sqr(x–6);
writeln(x,y);
x:=x+2;
i:=i+1;
goto d;
end.
x=3, i=1
i=1<4
y=9
3, 9
x=5
i=2
2<4
y=1
5, 1
x=7
i=3
3<4
y=1
7, 1
x=9
i=4
4=4
y=9
9, 9
x=11
i=5
5>4
конец
Оператор арифметического цикла. Принципы построения программ с арифметическими циклами можно проиллюстрировать обобщенной блок-схемой (см. рис. выше). Только обрабатывающая часть программы полезна. Остальные операторы являются обслуживающими, необходимыми для организации цикла. Построение цикла способами, описанными выше, неудобно. В виду этого в Паскале имеются специальные операторы цикла, упрощающие этот процесс.
Оператор цикла for:
ü FOR переменнаяцикла := начальноезначение ТО конечноезначение DO оператор
реализует приращение счетчика циклов на единицу в заданных пределах и контроль его значения. Цикл завершается в момент, когда переменная цикла становится больше конечного значения цикла. Например, оператор:
FOR a = 3 TO 7 DO WRITELN(a);
дословно интерпретируется следующим образом: “Оператор WRITELN после слова DO будет повторяться столько раз, сколько нужно, чтобы переменная А, изменяясь с шагом 1 от значения равного 3, достигла 7”. Т.е.: A=3; 4; 5; 6; 7 и цикл будет выполнен 5 раз. Если после слова DO поместить конструкцию begin...end, цикл может содержать неограниченное число операторов, например
FOR i = 1 TO n DO BEGIN WRITELN(i); READLN(x) END;
Имеется форма оператора, работающего на убывание (шаг равен –1).
ü FOR переменнаяцикла := начальноезначение DOWNТО конечноезначение DO оператор
В качестве параметров оператора цикла разрешены и выражения, например, FOR c=b+2 TO 4*k DO ...
Важно: все параметры-переменные в операторе FOR должны быть целого типа.
Задачи на накопление.В практике очень распространены задачи на накопление, т.е. на нахождение сумм и произведений последовательности переменных. Такие задачи могут встречаться как в формулировке итерационных, так и арифметических циклов.
Задача 5-4. Пусть требуется найти сумму N произвольных чисел Х. В программе P5_4 сумма накапливается в переменной S с помощью оператора S=S+X. Начальное значение суммы берется равным нулю (S=0).
Задание.Переделайте программу таким образом, чтобы она вычисляла еще среднее арифметическое и произведение.
Числовые ряды. Типичной циклической задачей на накопление является вычисление числовых рядов.
Задача 5-5. Пусть требуется найти сумму S для N членов геометрической прогрессии (справа). Здесь каждый следующий член прогрессии Аi равен предыдущему Ai-1, умноженному на два. Если учесть введенные обозначения, можно записать так называемые рекуррентные формулы:
Si = Si-1 + Ai, где Sо=0 Или, как принято S=S+A, S=0
Ai = 2Ai-1 A1=3. в программировании: A=2A, A=3.
Действие оператора FOR применительно к задаче отражено блок-схемой на рис. 5-5. Сам оператор FOR помещается в фигуру “прямоугольник в ромбе”, которая имеет два выхода. Выход ДА соответствует случаю, когда переменная цикла меньше или равна своему предельному значению (здесь I<=N) – цикл продолжает выполняться. Выход НЕТ – случаю превышения переменной этой границы – цикл завершается.
Аналогично строятся программы для циклического произведения, однако исходное значение искомого произведения берется равным единице. Если действовать по аналогии с суммой и сделать его равным нулю, то результат всегда будет также нулем, поскольку умножение на ноль дает только ноль.
Задание. Напишите программу вычисления произведения N элементов числового ряда.
Для формирования изменяющегося знака вводим специальную переменную Z и задаем ей первоначальное значение, совпадающее со знаком первого сомножимого (–1). Далее знак будет изменяться на противоположный при каждом умножении на минус 1 (Z=–Z).
program P5_6;
label t;
проверка для n=5 (х=3, –2, 1, –3, 2)
var i,n,kp:integer; x,s,p:real;
begin
цикл
цикл
цикл
цикл
цикл
readln (n);
kp:=0; s:=0; p:=1;
for i:=1 to n do begin
readln(x);
if x=0 then goto t;
if x<0 then s:=s+x;
if x>0 then begin
kp:=kp+1;
p:=p*x end;
end;
writeln(‘0 нет’);
t: writeln(s,p,kp);
end.
n=5
i=1<5
x=3
kp=1
p=3
2<5
x=–2
s=–2
3<5
x=1
kp=2
p=3
4<5
x=–3
s=–5
5=5
x=2
kp=3
p=6
6>5
0 нет
–5,6,3
Оператор цикла является сильнейшим средством программиста. Он один заменяет несколько операторов в цикле, построенном обычным образом, а именно: оператор задания исходного значения циклической переменной (или счетчика циклов) и операторы ее приращения и анализа.
Задача 5-6. Для N произвольных чисел Х вычислить и отпечатать:
1) сумму отрицательных чисел S, 2) количество положительных чисел КР, 3) произведение положительных чисел Р.
Все вычисления производить до появления первого нуля в последовательности. Если ноль не встретился, кроме S, KP и Р, печатать сообщение Нулей нет. Блок-схема алгоритма приведена на рис. 5-6. Проверка в программе сделана для N=5 и Х=3, –2, 1, –3, 2. В результате: S=–5, P=6, KP=3.
Задание. Программа имеет один дефект. Произведение положительных элементов может оказаться равным 1, как в случае, если оно действительно таким получилось, так и если положительных чисел не было совсем (ведь исходное значение произведения =1). Исправьте программу.