Рейтинг:  0 / 5

Звезда не активнаЗвезда не активнаЗвезда не активнаЗвезда не активнаЗвезда не активна
 

Сейчас мы рассмотрим некоторые типовые примеры на циклы.

1)найти сумму всех нечетных двузначных чисел

begin

  var s:integer:=0;

  for var i:integer:=11 to 99 do

  if (odd(i)) then

    s+=i;

  writeln(s);

end.

begin

  var s:integer:=0;

  var x:integer:=11;

  while x<100 do

  begin

    s+=x;

    x+=2;

  end;

  writeln(S);

end.

begin

  var s:integer:=0;

  var x:integer:=11;

  repeat

    s+=x;

    x+=2;

  until x>=100;

  writeln(S);

end.

label my;

begin

  var s:integer:=0;

  var x:integer:=11;

  my:begin

    s+=x;

    x+=2;

  end;

  if (x<100) then

    goto my;

  writeln(S);

end.

Во всех четырех програмных кодах тварится приблизительно одно и то же. В первом варианте цикл с параметром перечисляет все двузначные числа, а условный оператор отделяет четные числа от нечетных. Если число нечетное, то программа к значение переменной «s» прибавляет значение параметра «i» в условном операторе. После того, как программа пройдет весь цикл, программа выведет полученное значение.

В других примерах происходит примерно одно и то же: обьявляются две целочисленные переменные «х» и «s». Первая из них хранит текущее значение двузначного нечетного числа, а второе хранит текущую найденную сумму. Далее идут циклы до тех пор, пока переменная «x» меньше 100. В телах циклов к значению переменной «s» прибавляется текущее значение «х», а после этого к переменной «х» прибавляется 2, тем самым сохраняя ее нечетность. В последних трех примерах тварится одно и то же, различие которых отличается только в циклах, а алгоритмы, по которым программы работают, идентичны.

2) Вычислить n! = n*(n-1)*(n-2)*...*2*1

for

while

repeat

goto

begin

  var x:integer;

  write('n=');

  readln(x);

  var m:int64:=1;

  for var i:integer:=x downto 2 do

    m*=i;

  writeln(m);

end.

begin

  var x:integer;

  write('n=');

  readln(x);

  var m:int64:=1;

  while x>1 do

  begin

    m*=x;

    x-=1;

  end;

  writeln(m);

end.

begin

  var x:integer;

  readln(x);

  var m:int64:=1;

  repeat

    m*=x;

    x-=1;

  until x=1;

  writeln(m);

end.

Очевидно, что этот код не всегда будет работать.

label my,en;

begin

  var x:integer;

  readln(x);

  var m:integer:=1;

  if (x<0) then goto en;

  my:begin

    m*=x;

    x-=1;

    if (x<>1) then         goto my;

  end;

  en:writeln(m);

end.

Во всех примерах алгоритм работы один и тот же, только реализован разными способами. Вначале все программы считывают с клавиатуры значение, факториал которого нужно вычислить, затем идет цикл, высчитывающий факториал данного числа: значение переменной, которая хранит текущее найденное значение факториала умножается на текущее значение переменной «х», после чего значение переменной «х» уменьшается на 1. Тем самым обуспечивается выполнение формулы, высчитывающей факториа числа.

Обратите внимание, что в примере с циклом repeat программа будет далеко невсегда работать. Ее работоспособность будет сохраняться только тогда, когда будет введено положительное число. При отрицательном числе программа будет работать неправильно. А вообще все программы будут неправильно работать. Поскольку все программные коды приведены только для примера, то, если Вам необходима данная программа, то можете ее модифицировать и пользоваться ею. А модифицировать ее легко: поставить после ввода данных проверку на корректность с вызовом исключения или сделать бесконечный ввод, пока не будут выполнены все необходимые условия.

3) Посчитать сколько нечетных чисел среди n введенных

for

while

repeat

goto

begin

  var n:integer:=readinteger();

  assert(n>0);

  var c:integer:=0;

  for var i:integer:=1 to n do

    if (odd(readinteger())) then

      c+=1;

  writeln(c);

end.

begin

  var n:integer:=readinteger();

  assert(n>0);

  var c:integer:=0;

  var i:integer:=1;

  while i<=n do

  begin

    if (odd(readinteger())) then

      c+=1;

    i+=1;

  end;

  writeln(c);

end.

begin

  var n:integer:=readinteger();

  assert(n>0);

  var c:integer:=0;

  var i:integer:=1;

  repeat

    if (odd(readinteger())) then

      c+=1;

    i+=1;

  until i>n;

  writeln(c);

end.

label my;

begin

  var n:integer:=readinteger();

  assert(n>0);

  var c:integer:=0;

  var i:integer:=1;

  my:begin

    if (odd(readinteger())) then

      c+=1;

    i+=1;

  end;

  if (i<=n) then goto my;

  writeln(c);

end.

Опять же Мы видим, что все программы работают по абсолютно идентичному алгоритму. Единственное различие во всех этих программах - это цикл, который использовался при написании. А теперь разберем алгоритм.

Вначале обьявляется челочисленная переменная «n», значение которой считывается с клавиатуры. Затем идет проверка этого значения с помощью «assert». (Если Вам нужно эта программа для пользования, то ее лучше модифицировать). После этого обьявляется переменные «с», хранящая кол-во нечетных чисел, и «i», хранящая кол-во уже введенных чисел (можно было бы модифицировать: вместо того, чтобы создавать эту переменную, можно было бы вести циклы по условию: пока n>0 и все время значение этой переменной уменьшать на 1. На это все делается на вкус программиста. А вообще, что касается оптимизации, то второй вариант лучше). После этого идут циклы, которые выполняются до тех пор, пока выполняется условие i<=n. Далее в условном операторе считывается с клавиатуры число и проверяется оно на нечетность с помощью функции «odd». Если считанное значение нечетное, то к значению переменной «с» прибавляется 1. (!) (Внимание! Во всех вариантах программы компьютер не сохраняет считанное значение. Он его считывает с клавиатуры, проверяет на нечетность и «забывает» его. Если Вам нужно это значение, то создайте еще одну переменную, хранящую значение.). После этого при необходимости повторяется цикл.

4) Нахождение наибольшего общего делителя.

Если взять два любых числа, то для них найдется некоторое число, на которое делятся оба этих числа без остатка. И таких чисел может быть несколько для этих чисел. А наибольшее из них и называется Наибольшим Общим Делителем (НОД)

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

for

while

repeat

goto

var a,b:integer;

begin

  a:=abs(readinteger());

  b:=abs(readinteger());

  var max:=max(a,b);

  for var i:=0 to max do

  begin

    var c:=a mod b;

    a:=b;

    b:=c;

    if (b=0) then break;

  end;

  writeln(a);

end.

var a,b:integer;

begin

  a:=readinteger();

  b:=readinteger();

  while b<>0 do

  begin

    var c:=a mod b;

    a:=b;

    b:=c;

  end;

  writeln(a);

end.

var a,b:integer;

begin

  a:=readinteger();

  b:=readinteger();

  repeat

    if (b=0) then break;

    var c:=a mod b;

    a:=b;

    b:=c;

  until b=0;

  writeln(a);

end.

label my,en;

var a,b:integer;

begin

  a:=readinteger();

  b:=readinteger();

  my:begin

    if (b=0) then goto en;

    var c:=a mod b;

    a:=b;

    b:=c;

  end;

  goto my;

  en:writeln(a);

end.

Сразу видно, что первый код наиболее сложный по сравнению с другими. Для начала разберем его.

Обьявляются две переменные «а» и «b», которые считываются с клавиатуры и с помощью функции abs берутся по модулю (если число отрицательое, то оно домножается на -1, иначе ничего не делается). Берется еще одна переменная max, в которую записывается максимальное число среди чисел a u b. Далее идет цикл for от 0 до найденного максимума. Дальнейший код одинаковый со всеми примерами, поэтому я его обьясню чуть позже. В конце тела цикла стоит условный оператор, проверяющий, было ли найдено значение или нет. Если оно найдено, то программа прекращает работу.

Вы, наверное, спросите зачем мы берем модули числа? Действительно, лучше не брать модули, но без модулей мы не запустим цикл for-> этот цикл не совсем подходит для решения поставленной задачи и его лучше не использовать для нее.

Теперь разберем общий алгоритм. Данные программы основаны на алгоритме Евклида нахождения НОД. В полне очевидно, что перебирать все числа от 1 до минимума из этих двух чисел это не совсем эффективно. Но Евклид заметил одну особенность и составил следующий алгоритм:

1) нужно первое число поделить на второе и взять остаток от этого деления.

2) вместо первого числа записать второе, а вместо второго числа записать найденный остаток от деленя.

3)Если найденный остаток равен 0, то НОД - это первое число, иначе повторить с 1-го шага.

Рассмотрим действие этого алгоритма при нахожении НОД-а для чисел 72 и 140

начальные значения

конечные значения

1 шаг

а

72

140

b

140

72

2 шаг

a

140

72

b

72

68

3 шаг

a

72

68

b

68

4

4 шаг

a

68

4

b

4

0

Перед 0 стоит 4 -> это и есть НОД.

5)Найти сумму цифр целого положительного числа.

for

while

repeat

goto

begin

  var s:integer:=0;

  var m:integer:=readinteger();

  assert(m>0);

  for var i:=0 to m do

  begin

    s+=m mod 10;

    m:=m div 10;

    if (m=0) then break;

  end;

  writeln(s);

end.

begin

  var s:integer:=0;

  var m:integer:=readinteger();

  assert(m>0);

  while m>0 do

  begin

    s+=m mod 10;

    m:=m div 10;

  end;

  writeln(s);

end.

begin

  var s:integer:=0;

  var m:integer:=readinteger();

  assert(m>0);

  repeat

    s+=m mod 10;

    m:=m div 10;

  until m<=0;

  writeln(s);

end.

label my;

begin

  var s:integer:=0;

  var m:integer:=readinteger();

  assert(m>0);

  my:begin

    s+=m mod 10;

    m:=m div 10;

  end;

  if (m>0) then goto my;

  writeln(s);

end.

Во все программы я заложил один и тот же алгоритм: обьявляются две переменные. Одна из них хранит найденную сумму, а другое - текущее число. Далее идет цикл до тех пор, пока текущее число больше нуля, а в теле цикла к текущей сумме прибавляется последяя справа цифра числа, после чего число делится на 10 на цело. По-моему данная программа очень очевидна и проста.

6) Найти максимум/минимум среди n введеных

По-моему эта программа до более проста и оно схоже с 3 примером. Но мы все же рассмотрим на примере нахождения максимума.

for

while

repeat

goto

begin

  var n:integer:=readinteger();

  assert(n>0);

  var max:integer:=integer.MinValue;

  for var i:=1 to n do

  begin

    var c:integer:=readinteger();

    if (c>max) then max:=c;

  end;

  writeln(max);

end.

begin

  var n:integer:=readinteger();

  assert(n>0);

  var max:integer:=integer.MinValue;

  var i:integer:=1;

  while i<=n do

  begin

    var c:integer:=readinteger();

    if (c>max) then max:=c;

    i+=1;

  end;

  writeln(max);

end.

begin

  var n:integer:=readinteger();

  assert(n>0);

  var max:integer:=integer.MinValue;

  var i:integer:=1;

  repeat

    var c:integer:=readinteger();

    if (c>max) then max:=c;

    i+=1;

  until i>n;

  writeln(max);

end.

label my;

begin

  var n:integer:=readinteger();

  assert(n>0);

  var max:integer:=integer.MinValue;

  var i:integer:=1;

  my:begin

    var c:integer:=readinteger();

    if (c>max) then max:=c;

    i+=1;

  end;

  if (i<=n) then

    goto my;

  writeln(max);

end.

Алгоритмы этих всех программ более чем очевидны. Единственное, что Вы не знаете, так это строку «integer.MinValue;». Эта функция возвращает самое имнимальное значение, которое может в себе хранить тип интеджер. А что тварится дальше Вы, наверное, дагадываетесь. (создаются две переменные, одна из которых хранит кол-во значений, которое будет введено, а второе - текущий найденный максимум (поскольку мы не знаем, какие числа нам будут вводиться, то мы воспользуемся специфичным значением - самым минимальным значением, которое может хранить тип данных integer). Далее идет цикл по кол-ву вводимых значений, внутри которого создается новая переменная «c», в которую считывается значение с клавиатуры, после чего идет проверка на то, что данное число больше найденного максимума. Если это так, то текущий максимум меняется).

Вы, наверное, заметили что в каждом примере очень схожие алгоритмы, только цикл разный. Так вот вывод: для каждого конкретного задания нужно подобрать наиболее подходящий цикл, если он требуется. И писать программу так как Вам удобно. Выберете для себя наиболее удобный для Вас цикл или два цикла и пишите программы на них. Для меня это циклы while и for. Что для Вас удонее - Вам и решать.

Далее будут задачи на программирование, которые Вы можете решить и, если хотите, можете отправить свою работу нам на проверку. Для того, чтобы ее нам отправить Вам нужна будет регистрация.