четверг, 21 октября 2010 г.

Как научиться программировать циклы?

Циклы - это структура достаточно сложная для понимания и программирования.
Рассмотрим пример составления программы на Паскале. Перед этим лучше дать шаблон описания циклических алгоритмов. Мы будем разбирать цикл с параметром (его очень сложно понять начинающим программистам).
Лучше использовать для понимания пример вычисления суммы ряда. Пусть это будет сумма 1+1/2+1/3+1/4+1/5+ ...+1/1000. Видно, что таких чисел нужно писать очень много. Нельзя ли это как нибудь автоматизировать? Для этого используем циклический алгоритм.
Пусть сумма хранится в переменной S (Важно понять, что переменная меняет свое значение после оператора присваивания). Итак, возникает вопрос: что тут будет телом цикла? и сколько раз выполнится цикл?
Пока не понятно что есть что, предположим, что каждый раз в теле цикла будет прибавляться (увеличиваться) к сумме (переменная S) следующее слагаемое. Выпишем все суммы по порядку увеличения количества слагаемых.
На начальном (нулевом) шаге считаем, что S=0 (ничего не прибавили, нет слагаемых).
1-й шаг S=1
2-й шаг S=1+1/2
3-й шаг S=1+1/2+1/3
4-й шаг S=1+1/2+1/3+1/4
и т.д.
Видно, что каждый раз в сумме повторяется некоторое количество слагаемых (они подчеркнуты). Оператор присваивания работает справа налево: сначала вычисляется выражение, а потом присваивается результат в переменную. Если мы запишем S=S+1 это будет означать, что берем значение из переменной S (оно равно на нулевом шаге 0) и прибавим 1, в результате получаем 1; и только после этого заменяем значение переменной S на 1, т.е. теперь S равно не 0, а 1.
Таким образом, следующим шагом будет S=S+1/2 - это будет означать, что берем значение из переменной S (оно равно на 1-м шаге 1) и прибавим 1/2, в результате получаем 1+1/2; и только после этого заменяем значение переменной S на 1+1/2, т.е. теперь S равно не 1, а 1+1/2.
Продолжая рассуждения получим следующий линейный алгоритм:

0-й шаг S=0
1-й шаг S=S+1
2-й шаг S=S+1/2
3-й шаг S=S+1/3
4-й шаг S=S+1/4
 и т.д.

Теперь видно, что какую-то часть можно считать постоянной частью и выделить в тело цикла. Но шаги и слагаемые меняются. Как решить эту проблему? Обозначим, номер шага за переменную K. Тогда линейный алгоритм запишется так:

0-й шаг K=0; S=0

1-й шаг K=1; S=S+1/K
2-й шаг K=2; S=S+1/K
3-й шаг K=3; S=S+1/K
4-й шаг K=4; S=S+1/K
и т.д.
Теперь видно, что S=S+1/K повторяется каждый раз для каждого следующего K. K меняется от 1 до 1000.  Для этой переменной можно организовать цикл с параметром FOR K:=1 TO1000 DO, а в теле цикла запишем S:=S+1/K. Получим следующий циклический алгоритм вместо линейного:
FOR K:=1 TO1000 DO 
         S:=S+1/K;
Видно, что эти две строчки ничто, по сравнению с 1000 строчками линейного.
Спросите, зачем огород городить? На самом деле такие задачи обычно решаются с заданным ограничением: количество слагаемых (обозначим за переменную N). И если записать для каждого числа такие суммы, то будет ОЧЕНЬ МНОГО строк в программе. Конечно, можно копировать и вставлять, но лучше записать так:

READLN(N);
FOR K:=1 TO N DO 
         S:=S+1/K;
 Все!
Я привела такой подробный текст, чтобы видно было ход моих рассуждений, как пришли к циклу. Если просто записать цикл и от него уже объяснять как работает цикл - никогда не научитесь программировать циклы.
Попробуйте самостоятельно составить циклы для сумм:
a) sin 1+ sin 2+sin 3 + ... + sin n
b) x+x^2+x^3+x^4+...+x^n (не используя функцию возведения в степень и лишних циклов)
с) 1+1*2+1*2*3+...+n! (n!=1*2*3*...*n - не используя лишних операторов цикла)
d) sin x+ sin sin x + sin sin sin x+ ... + sin ... sin x (количество вызовов функции sin будет n)

Комментариев нет:

Отправить комментарий