Цикл - это замечательное изобретение, которое, в сущности, и делает компьютеры
такими ценными. Он позволяет многократно повторить любую часть программы. Цикл
не может выполняться вечно, он заканчивается по какому-либо условию. Проверка
этого условия может производиться в начале каждого повторяющегося шага, в этом
случае цикл называется ПОКА. При проверке условия в конце каждого шага цикл
называется ДО. Разновидностью цикла ДО является цикл ПЕРЕСЧЕТ.
10.1.Оператор цикла WHILE (цикл
ПОКА).
Формат оператора:
WHILE логическое выражение
DO;
Оператор будет повторятся пока истинно логическое выражение. Перед каждым
повторением оператора значение логического выражения вычисляется заново. Если
необходимо повторить несколько операторов, их следует объединить в составной
оператор, т.е. заключить в операторные скобки begin ... end. Этот цикл может не
выполниться ни разу, если условие при входе в него оказалось ложным. Таким
образом, цикл ПОКА содержит условие повторения цикла.
Пример 1.
Программа подсчета суммы S первых 1000 членов гармонического ряда
1+1/2+1/3+1/4+...1/N.
Program Summa;
Var S:real;
N:integer;
Begin
S:=0;N:=0;
While n<1000 do
Begin
N:=n+1;
S:=s+1/n
End;
Writeln(s);
Readln
End.
Пример 2.
Вычислить наибольший общий делитель двух натуральных чисел А и В.
Воспользуемся для этого алгоритмом Евклида: будем уменьшать каждый раз большее
из чисел на величину меньшего до тех пор, пока оба числа не станут равны.
Program NOD;
Var a,b:integer;
Begin
Write ('введите
два
натуральных
числа')
Readln(a,b)
While a<>b do If a>b then a:=a-b else b:=b-a;
Writeln('НОД=',a);
Readln
End.
Пример 3
.
Начав тренировки, лыжник в первый день пробегал 10 км. Каждый следующий день он
увеличивал длину пробега на 10% от предыдущего дня. Определить в какой день он
пробежит больше 20 км, в какой день суммарный пробег за все дни превысит 100км.
Program prim_10;
Var S:real;
N:integer;
Begin
S:=10;N:=1;
While s<20 do
Begin
N:=n+1;
S:=s*0.1
End;
Writeln(' дневной пробег больше 20 км на ',n,' день');
S:=10;N:=1;
While s<100 do
Begin
N:=n+1;
S:=s+s*0.1 {накапливаем суммарный пробег}
End;
Writeln('за ',n,' пробежит больше 100 км');
Readln
End.
Тренировочные задания.
1. Даны целые числа а и b (а>b). Определить:
a. Результат целочисленного деления a на b, не используя стандартную операцию
целочисленного деления;
b. Остаток от деления а на b не используя стандартную операцию вычисления
остатка.
2. Известны оценки по информатике каждого из 20 учеников класса. В начале списка
перечислены все пятерки, затем все остальные оценки. Сколько учеников имеют по
информатике оценку "5"?. Условный оператор не использовать.
3. Напечатать минимальное число, большее 200, которое нацело делится на 17.
4. Гражданин 1 марта открыл счет в банке, вложив 1000 руб. Через каждый месяц
размер вклада увеличивается на 2% от имеющейся суммы. Определить: за какой месяц
величина ежемесячного увеличения вклада превысит 30 руб.; через сколько месяцев
размер вклада превысит 1200 руб.
5. *В некоторой стране используются денежные купюры достоинством в 1, 2, 4, 8,
16, 32 и 64. дано натуральное число N. Как наименьшим количеством таких денежных
купюр можно выплатить сумму N (указать количество каждой из используемых для
выплаты купюр)? Предполагается, что имеется достаточно большое количество купюр
всех достоинств.
Разбор заданий урока 9.
5. Дано четырехзначное число N. Выяснить:
a. Является ли число палиндромом?
Для решения этой задачи надо записать число в обратном порядке. Для этого
единицы умножаем на 1000, прибавляем число десятков умноженное на 100, число
тысяч умножаем на 10 и прибавляем число десятитысяч. Если полученное число будет
равно исходному, значит это палиндром.
Program prim9_5а;
Var x,y:integer;
Begin
Write('введите четырехзначное число');
Readln(х);
y:=(x mod 10)*1000+((x div 10) mod 10)*100+((x div 100) mod 10)*10+x div 1000;
If x=y then writeln ('число палиндром ')
Else Writeln('это не палиндром ');
Readln;
End.
6. Трамвайный билет имеет шестизначный номер. Выяснить, является ли билет
"счастливым". Билет назовем "счастливым", если сумма первых трех цифр равна
сумме последних трех цифр. Примечание. Так как шестизначное число больше 32767
(тип Integer), необходимо номер билета определит как тип Longint(до 10 знаков).
Program prim9_6;
Var x1,x2:integer;
x,:longint;
Begin
Write('введите номер билета');
Readln(х);
X1:=x div 100000+(x div 10000) mod 10+(x div 1000) mod 10; {сумма первых трех
цифр}
X2:=(x div 100) mod 10+(x div 10) mod 10+x mod 10; {сумма последних трех цифр}
If x1=x2 then writeln (' билет счастливый ')
Else Writeln('билет не счастливый ');
Readln;
End.
Продолжим знакомство с операторами цикла, имеющимися в Паскале. Повторение
группы операторов (тела цикла) можно организовать и с помощью оператора, где
проверка условия осуществляется после выполнения тела цикла.
11.1.Оператор цикла REPEAT (цикл
ДО).
Формат оператора:
REPEAT оператор;
оператор;...оператор UNTIL логическое условие;
Часть программы, заключенная между служебными словами REPEAT и UNTIL,
повторяется до тех пор, пока не станет истинным логическое выражение, стоящее
после слова UNTIL. Между словами REPEAT (повторить) и UNTIL(до тех пор, пока)
можно записать любое количество операторов без использования операторных скобок.
В отличие от оператора WHILE вычисление логического выражения происходит не
до, а после очередного повторения цикла. Из-за этого цикл REPEAT обязательно
выполнится хотя бы раз, а цикл WHILE может не выполнится ни разу. Если условие в
цикле ПОКА является условием продолжения повторений, то условие в цикле ДО -
условием выхода из цикла, его завершения. Поэтому для одной и той же задачи эти
условия противоположны.
Пример 1.
Составить программу подсчета суммы S первых 1000 членов гармонического ряда
1+1/2+1/3+1/4+...1/N используя оператор цикла REPEAT.
Program Summa;
Var S:real;
N:integer;
Begin
S:=0;N:=0;
repeat
N:=n+1;
S:=s+1/n
Until n>1000;
Writeln(s);
Readln
End.
11.2.Поиск наибольшего числа.
Предположим, нам необходимо ввести с клавиатуры N чисел, найти из них
наибольшее и вывести его. Для решения этой задачи предлагается следующий
алгоритм:
1. Ввести первое число в переменную Max.
2. Ввести следующее число в переменную Next.
3. Если Next>Max, то Max:=Next.
Пункты 2 и 3 повторять, пока не будут введены все числа.
4. Вывести значение переменной Max.
Действительно ли будет напечатано наибольшее из N чисел? Докажем это.
После выполнения первого пункта в переменной Max находится наибольшее из уже
введенных чисел. Это справедливо, т.к. введено лишь одно число.
Повторение пунктов 2 и 3, в сущности, представляет собой цикл, который
выполняется, пока не будут введены все числа. Если перед очередным повторением
цикла в Max находится наибольшее из введенных чисел, то после выполнения пунктов
2 и 3 там снова будет наибольшее из введенных чисел.
В последнем пункте значение Max будет выведено.
Этот пример показывает, что алгоритм можно доказать, как доказывают
математическую теорему. Программируя доказательный алгоритм, можно не опасаться
ошибок в алгоритме, конечно, если нет ошибок в доказательстве.
Program maximum;
Var N, max, next, k: integer;
Begin
Write('Введите количество чисел'); Readln(n);
Write('Введите число'); Readln(max);
k:=1;
repeat
Write('Введите число'); Readln(next);
K:=k+1;
If next>max then max:=next
Until k=n;
Writeln(max);
Readln
End.
Тренировочные задания.
1. Введите с клавиатуры 6 чисел и определите их среднее арифметическое.
2. Напишите программу, которая вводит целые числа с клавиатуры и складывает их,
пока не будет введено число 0.
3. Напечатайте 20 первых степеней числа 2.
4. Найдите минимальное из N чисел.
5. Дано натуральное число. Выяснить, является ли оно простым, т.е. делится
только на 1 и на само себя.
Сегодня мы познакомимся с оператором, который обеспечивает повторение цикла,
управляемое переменной.
13.1. Цикл ПЕРЕСЧЕТ (прямой).
Формат оператора:
FOR переменная :=
выражение 1 ТО
выражение 2 DO
оператор;
Переменная должна быть порядкового типа. Порядковыми называются все простые
типы, значения которых можно расположить в возрастающем порядке. Из известных
нам это: INTEGER, WORD, LONGINT, BYTE, CHAR. Выражение 1 и Выражение 2 должны
быть того же типа, что и переменная. Чтобы цикл выполнился хотя бы раз
выражение1 должно быть не больше выражения2.
Выполнение начинается с вычисления значений выражения1 и выражения2. затем
переменная получает значение выражения1 и делается проверка, не превышает ли
значение переменной выражения2. Если не превышает, выполняется оператор стоящий
после служебного слова DO. После завершения оператора переменная получает
следующее по порядку значение, и все повторяется, начиная с проверки.
Когда значение переменной становится равным выражению2, оператор выполняется
последний раз.
ПРИМЕР 1.
Напечатать ряд из повторяющихся чисел 20 в виде:
20 20 20 20 20 20 20 20 20 20
Код программы:
var i: byte;
begin
for I:=1 to 10 do write(20,' ');
readln;
end.
ПРИМЕР 2.
Напечатать числа следующим образом:
10 10.4
11 11.4
. . .
25 25.4
Код программы (переменная используется не только для управления циклом но и для
вывода на экран в качестве результата):
var i: byte;
begin
for I:=10 to 25 do write(I,' ',I+0.4:0:1);
{при сложении целого I и вещественного 0.4 получаем
вещественный результат, значит надо выполнить его
форматирование при выводе на экран}
readln;
end.
13.2. Цикл ПЕРЕСЧЕТ (обратный).
Возможен вариант оператора, когда переменная принимает последовательно
убывающие значения.
Формат оператора:
FOR переменная :=
выражение 1 DOWNТО
выражение 2 DO
оператор;
В этом случае, чтобы цикл выполнился хотя бы раз, выражение1 должно быть не
меньше выражения2. Например:
For c:='z' downto 'а' do writeln(с);
Тренировочные задания.
1.Напечатать столбиком:
а) все целые числа от 20 до 35;
б) квадраты всех целых чисел от 10 до b (значение d вводится с клавиатуры; b>=10);
в) третьи степени всех целых чисел от а до 50 (значение а вводится с
клавиатуры; а<=50);
г) все целые числа от а до b (значения а и b вводятся с клавиатуры; d>=a).
2. Напечатать числа следующим образом
25 25.5 24.8
26 26.5 25.8
. . .
35 35.5 34.8
3. Распечатать в столбик таблицу умножения на 7.
4. Вывести столбиком следующие числа: 2,1 2,2 2,3 . . . , 2,8
5. Вывести столбиком следующие числа: 2,2 2,4 2,6 . . . , 4,0 4,2
6. Вывести столбиком следующие числа: 4,4 4,6 4,8 . . . , 6,2 6,4
Задача
1.
Дано
натуральное число N. Определить, является ли оно простым, т.е. делится нацело
только на 1 и на само себя. (Мы решали эту задачу в 12 уроке, но я хочу
предложить вам другой алгоритм решения.)
Для решения необходимо проверить, делится ли исходное число на числа от 2 до
N-1. Если число делится хотя бы на одно из чисел без остатка, то число N не
будет простым. Мы можем уменьшить интервал проверяемых делителей так, как
наибольший из возможных, это N/2. Введем так же дополнительную переменную F, она
будет принимать значение 1, если обнаружится хотя бы один из делителей для
исходного числа. Первоначально присвоим F значение 0, т.е. предположим, что
число простое.
Переменные:
N - исследуемое число;
I - переменная цикла;
F - вспомогательная переменная.
Код программы.
Var I,n,f:word;
Begin
Write('Введите натуральное число');
Readln(n);
F:=0;
For I:=2 to n div 2 do if n mod I=0 then f:=1;
If f=1 then writeln('число',n:6,' не простое')
Else writeln('число',n:6,' простое');
Readln
End.
Количество выполнения циклов можно еще уменьшить. Ведь на самом деле если
число N делится на какое-то число А без остатка (кроме 1 и самого себя), то оно
имеет и второй делитель В=N/A, т.е. если число не простое то его всегда можно
записать как N=A*B. При возрастании первого делителя, значение второго будет
уменьшаться. Получается, что достаточно проверить все числа от 2 до SQRT(n), но
так как результат вычисления корня вещественный, а параметр цикла должен иметь
целое значение, применим функцию определения целой части числа TRUNC, и получим:
For I:=2 to trunc(sqrt(n)) do if n mod I=0 then f:=1;
Задача 2.
Даны натуральные числа M и N. Определить, являются ли они взаимно простыми.
Взаимно простые числа не имеют общих делителей, кроме 1.
Для решения задачи:
- вводим натуральные числа М и N;
- в цикле от 2 до наименьшего числа порождаем I и проверяем, является ли оно
одновременно делителем М и N;
- в зависимости от значения F выводим результат.
Var k,m,n,f:word;
Begin
Write('Введите 2 натуральных числа');
Readln(n,m);
F:=0;
if n>m then k:=m else k:=n; {k - наименьшее из 2-х чисел }
for I:=2 to k do if (n mod I=0) and (m mod I = 0) then f:=1;
If f=1 then writeln('числа не взаимно простые')
Else writeln('числа взаимно простые');
Readln
End.
Тренировочные задания.
1. Дан интервал натуральных чисел от N до М. Определить все простые числа в этом
интервале.
2. Дано натуральное число N. Определить все простые числа не превосходящие N.
3. Дано натуральное число N. Разложить его на простые множители.
4. Дано натуральное число N. Определить, является ли оно совершенным.
Совершенное число N равно сумме всех своих делителей, не превосходящих само N.
5. Дано натуральное число N. Определить, является ли оно автоаморфным.
Автоаморфное число N равно последним разрядам квадрата этого числа: 5<->25,
6<->36, 25<->625.
Сегодняшний урок мы посвятим обработке числовых последовательностей. Для этого
обычно используется оператор цикла.
Алгоритмы для обработки последовательностей чаще относятся к одному из двух
типов: поиск; проверка условий.
Для последовательностей характерно, что в каждый момент времени нам доступен
только один элемент последовательности. Поэтому все алгоритмы строятся с учетом
однократного последовательного просмотра.
Рассмотрим несколько программ. В каждой из них одновременно рассматривается
только очередной член последовательности. Алгоритмы для решения таких задач
называются алгоритмами с линейным поиском.
Задача 1.
Вводится последовательность из N целых чисел. Найти сумму всех отрицательных
чисел.
Код программы.
Var I,n,x,sum:integer;
Begin
Write('Введите длину последовательности N=');
Readln(n);
Sum:=0;
For I:=1 to n do
Begin
Write('Введите число');
Readln(x);
if x<0 then sum:=sum+x
end;
If sum=0 then writeln('отрицательных чисел нет')
Else writeln('сумма отрицательных чисел =', sum);
Readln
End.
Задача 2.
Вводится последовательность ненулевых чисел, 0 - конец последовательности.
Определить, сколько раз последовательность меняет знак.
Var old, new: real;
K: integer;
Begin
Write('введите число');
Readln(old);
Write('введите число');
Readln(new);
K:=0;
Repeat
If new*old<0 then k:=k+1;
Old:=new;
Write('введите число');
Readln(new);
Until new=0;
If k>0 then writeln ('Последовательность меняет знак ',k,' раз')
else writeln ('Последовательность не меняет знак ');
readln;
end.
Тренировочные задания.
1. Вводится последовательность из n произвольных чисел. Определить, сколько раз
последовательность меняет знак.
2. Вводится последовательность чисел, 0-конец последовательности. Определить,
содержит ли последовательность хотя бы два равных соседних числа.
3. Вводится последовательность чисел, 0-конец последовательности. Найти два
наименьших числа.
4. Вводится последовательность из N целых чисел. Найти наибольшее из всех
отрицательных чисел.
5. Вводится последовательность из N целых чисел. Найти, сколько в ней нулей.
Разбор заданий урока.
3. Дано натуральное число N. Разложить его на простые множители.
Var n,I,j:word;
F:Byte;
Begin
Write('Введите натуральное число');
Readln(n);
Write(n:6,'=1'); {любое число имеет множитель 1}
F:=0;
J:=n;
for I:=2 to n div 2 do
begin
if j mod I=0 then
begin
f:= 1; {найден множитель больше 1}
while j mod i = 0 do
{цикл определяет, сколько множителей I в исходном числе N}
begin
write('*',i);
j:=j div I
end;
end;
end;
If f=0 then writeln('*',n);
Readln
End.
4. Дано натуральное число N. Определить, является ли оно совершенным.
Совершенное число N равно сумме всех своих делителей, не превосходящих само N.
Var n,i,sum:word;
Begin
Write('Введите
натуральное
число');
Readln(n);
Sum:=0;
for i:=1 to n div 2 do if n mod I=0 then sum:=sum+i;
If sum=n then writeln('число
',n,'
совершенное')
Else writeln(('число
',n,'
не
совершенное'
);
Readln
End.
5. Дано натуральное число N. Определить, является ли оно автоморфным.
Автоморфное число N равно последним разрядам квадрата этого числа: 5<->25,
6<->36, 25<->625.
Var n,r,m:word;
Begin
Write('Введите натуральное число');
Readln(n);
M:=n; r:=1;
While m>0 do {в цикле определяем разрядность введенного числа (r)}
Begin
M:=m div 10;
R:=r*10;
End;
If (n*n mod r)=n then writeln('число ',N,' автоморфно')
Else writeln(('число ',N,' не автоморфно' );
Readln
End.
Оставим пока числовые последовательности, их существует большое многообразие и
позднее мы к ним вернемся. А сейчас попробуем решить следующую задачу:
Составить программу, которая в зависимости от порядкового номера дня недели
(1, 2, ..., 7) выводит на экран его название (понедельник, вторник, ...,
воскресенье).
Для этого воспользуемся условным оператором.
Var x: byte;
Begin
Write(' введите число от 1 до 7');
Readln(x);
If x=1 then writeln('понедельник');
If x=2 then writeln('вторник');
If x=3 then writeln('среда');
If x=4 then writeln('четверг');
If x=5 then writeln('пятница');
If x=6 then writeln('суббота');
If x=7 then writeln('воскресенье');
Readln
End.
А если бы речь шла о названия месяца, то операторов пришлось бы использовать
еще больше, так как условный оператор позволяет осуществлять ветвление программы
только по двум направлениям, одно из которых соответствует выполнению
проверяемого условия, а другое - невыполнению этого же условия. А если для
переменной необходимо выполнить в зависимости от условий ряд действий придется
использовать вложенные операторы или несколько операторов подряд.
В таком случае лучше подойдет оператор ВАРИАНТА (или ВЫБОРА).
Если условный оператор напоминает дорожную развилку, то оператор выбора - это
разделение пути на множество дорог, по одной из которых пойдет выполнение
программы.
Формат оператора:
CASE выражение OF
P1:<оператор 1>;
P2:<оператор 2>;
. . .
PN:<оператор N>;
ELSE <оператор N+1>
END;
Выражение порядкового типа вычисляется, и его значение отыскивается в одном из
списков констант. После этого выполняется соответствующий оператор. Если
значение выражения не совпало ни с одной из меток, то выполняется оператор из
строки ELSE. Cокращенная форма оператора не содержит ELSE. Метки оператора
варианта могут быть константами любого типа, но их тип должен совпадать с типом
выражения.
Тогда код нашей программы будет выглядеть иначе:
Var x: byte;
Begin
Write(' введите число от 1 до 7'); Readln(x);
Case x of
1: writeln('понедельник');
2: writeln('вторник');
3: writeln('среда');
4: writeln('четверг');
5: writeln('пятница');
6: writeln('суббота');
7: writeln('воскресенье');
end;
Readln
End.
Если при выборе альтернативы необходимо выполнение нескольких операторов, то
нужно заключить их в операторные скобки BEGIN . . . END;, т.е. использовать
составной оператор.
При использовании оператора CASE можно использовать диапазон допустимых
значений параметра. Например, чтобы определить, введена ли как символьная
переменная цифра, можно написать:
CASE I OF
'0'..'9':writeln('цифра');
ELSE writeln ('не цифра')
END;
Задача. Для
целого числа K от 1 до 99 напечатать фразу "Мне k лет", учитывая при этом, что
при некоторых значениях K слово "лет" надо заменить на слово "год" или "года".
Например, 11 лет, 22 года, 51 год. (Данное решение можно улучшить используя
дополнительно условный оператор. Попробуйте.)
var k:byte;
begin
write('Введите число лет'); readln(k);
case k of
1,21,31,41,51,61,71,81,91:writeln('Мне ',k,' год');
2..4,22..24,32..34,42..44,52..54,62..64,72..74,82..84,92..94:writeln('Мне ',k,'
года');
else writeln('Мне ',k,' лет');
end;
readln;
end.
Тренировочные задания:
1. Составить программу, которая в зависимости от порядкового номера месяца (1,
2, ..., 12) выводит на экран его название (январь, февраль, ..., декабрь).
2. Написать программу, которая бы по введенному номеру месяца выдавала
соответствующее этому месяцу время года.
3. Составить программу, которая читает натуральное число N в десятичном
представлении (N<=10000), а на выходе выдает это же число в десятичном
представлении и на естественном языке. Например: 7 - семь, 204 - двести четыре,
52 - пятьдесят два.
Задачи на повторение:
4. Дано натуральное число. Определить, является ли разность его максимальной и
минимальной цифр четным числом.
5. Дано натуральное число. Определить, сколько раз в нем встречается цифра,
равная старшей.
<<Назад