Цикл с предусловием реализуется с помощью инструкции

Цикл заставляет интерпретатор JavaScript многократно выполнять один и тот же блок кода, называемый телом цикла. Каждое отдельное исполнение инструкций в теле цикла называется итерацией. В JavaScгipt доступны четыре инструкции циклов: while, do/while, for и for/in.

Цикл while

Инструкция while (англ. до тех пор, пока) создает цикл с предусловием. В скобках после слова while указывают некоторое логическое выражение или значение. Цикл начнется если значение этого выражения равно true и будет работать до тех пор, пока это условие не обратится в false. Общий синтаксис этого цикла выглядит так:

while (условие) {
  инструкция
}

Циклы while|for

Следующий цикл while исполняется, пока значение переменной i меньше 3:

После окончания третьей итерации условие i < 3 больше не является истинным, поэтому цикл завершается.

Для создания бесконечного цикла в качестве условия достаточно задать булево значение true:

while (true) {
  инструкция
}

Это общепринятый способ создания бесконечного цикла. В прочих случаях (к примеру, если в рассмотренном нами примере убрать в коде i++) возможен вариант (в теории) создания бесконечного цикла. На практике, браузер выведет сообщение о «зависшем» скрипте и посетитель его остановит.

Цикл do…while

Инструкция do…while (англ. делай до тех пор, пока) отличается от цикла while тем, что в do…while сначала выполняется тело цикла, а затем проверяется условие продолжения цикла. Из-за такой особенности do…while называют циклом с постусловием. Таким образом, если условие do…while заведомо ложное, то хотя бы один раз блок операторов в теле цикла do…while всё равно выполнится.

Инструкция do…while представляет собой конструкцию из двух операторов, используемых совместно. Синтаксис этой конструкции следующий:

do {
  // тело цикла
} while (условие);

Пример do…while:

Этот цикл продолжается, пока переменная i меньше 4. Она равна 0 в начале цикла и увеличивается на 1 на каждой итерации.

На заметку: Циклы с постусловием обычно используются, если тело цикла должно быть выполнено хотя бы один раз.

Цикл for

Инструкция for – это вариант цикла с предусловием, который состоит из трех необязательных выражений, заключенных в круглые скобки и разделенных точками с запятой, за которым следует оператор (обычно оператор блока), который должен выполняться в цикле. Она имеет следующий синтаксис:

for (инициализация; выражение; обновление) {
  // ... тело цикла ...
}

Описание синтаксиса:

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

Пример цикла for:

Рассмотрим выполнение этого цикла более подробно:

  1. Инициализация: Переменная-счетчик, в данном случае х, инициализируется значением 1. Выполняется один-единственный раз, при заходе в цикл.
  2. Выражение: x < 4 – это условие продолжения цикла for, оно проверяется перед каждой итерацией и при входе в цикл на истинность. Если это так, то выполняются инструкции тела цикла (в данном случае – инструкция alert( x + » » );).
  3. Обновление: x++ – изменяет значение переменной-счетчика. Выполняется после тела на каждой итерации, но перед проверкой условия x < 4.
  4. Тело цикла: alert( x + » » ) – тело цикла обрамляется фигурными скобками, если тело цикла состоит из одной операции, то фигурные скобки можно опустить.

Иными словами, поток выполнения цикла: Инициализация → (если условие выражения true → тело цикла → обновление (x++)) → (если условие выражения true → тело цикла → обновление (x++)) → … и так далее, пока верно условие – x < 4.

Циклы for могут быть более сложными, чем в приведенных выше примерах. В некоторых циклах на каждой итерации может изменяться одновременно несколько переменных. В таких циклах часто применяется оператор «запятая» – он позволяет объединить несколько выражений инициализации и инкрементирования в одно, например:

Использование for без блоков

Все три выражения в заголовке цикла for являются необязательными.

Например, в блоке инициализации не требуется инициализировать переменные. Цикл в примере ниже полностью идентичен приведённому выше:

Как и блок инициализации, блок выражения также не является обязательным. Если вы опускаете выражение, то вы должны обязательно разбить цикл в теле, чтобы не создавать бесконечный цикл:

Можно опустить все три блока. Для избежания зацикливания используйте break для завершения цикла, а также изменяйте (увеличивайте или уменьшайте) переменную-счётчик, так чтобы условие для оператора break в какой-то момент сработало:

Примечание: Любое из выражений в цикле for может отсутствовать, однако сами точки с запятой обязательно должны присутствовать, иначе будет синтаксическая ошибка.

Цикл for…in

Цикл for…in используется для перебора всех свойств из объекта в случайном порядке и имеет следующий синтаксис:

for (variable in object) {
  инструкция /* ... делать что-то с object[variable] ... */
}

В качестве nеременной (variable) можно подставить имя переменной или инструкцию var, объявляющую одну переменную. Переменной перед началом каждой итерации цикла присваивается в виде строки имя одного из свойств объекта. Как и в цикле for, оператор var здесь не обязателен, но его рекомендуется использовать, чтобы переменная была локальной. Справа от ключевого слова in указывается объект, свойства которого будут перебираться циклом. Если переменная, представляющая объект, будет иметь значение null или undefined цикл не выполнится ни разу. И как обычно, инструкция – это инструкция или блок инструкций, образующих тело цикла.

Пример итерации по свойствам объекта:

Как отмечалось ранее, если имя свойства хранится в переменной, то обратиться к нему можно только через квадратные скобки (myCar[prop]), а не через оператор «точка».

Свойства объектов в JavaScript не упорядочены, поэтому порядок возврата их имен в цикле for…in предсказать сложно. Все перечислимые свойства будут возвращены, но порядок их вывода может зависеть от браузера.

Согласно стандарта ECMAScript, если имя свойства – нечисловая строка, то такие свойства всегда перебираются в том же порядке, в каком присваивались. Так получилось в примере выше при выводе свойств объекта myCar.
С другой стороны, если в качестве имени свойства выступает число или строка, которая может быть преобразована в числовой фомат, то браузеры осуществлят сортировку таких свойств в целях внутренней оптимизации. Вывод таких имен свойств объекта не будет соответствовать их оригинальному расположению.

Вложенные циклы

Цикл внутри другого цикла называется вложенным. Вложенность циклов формально не ограничивается, однако нужно быть предельно осторожным, чтобы не допустить зацикливания. При каждой итерации внешнего цикла вложенный цикл выполняется полностью. Вложенные циклы можно создавать с помощью инструкции for и инструкции while.

Пример вложенного цикла:

Теперь попытаемся разобраться, как это работает. Первый (внешний) цикл после каждой итерации увеличивает значение переменной i, а второй (внутренний) – переменной j. За одну итерацию внешнего цикла внутренний выполняется девять раз. По условию (i < 10) внешний цикл выполнится 9 раз. Соответственно вложенный цикл будет выполнятся тоже 9 раз, а код внутри него – 9*9 итого 81 раз.

Иными словами, код читаем так: натыкаемся на внешний цикл, делаем первый проход, во время прохода натыкаемся на еще один цикл (внутренний), делаем девять проходов по нему, каждый раз выводя текущее значение переменной j. Выводим значение i и далее возвращаемся в начало внешнего цикла для второго прохода и так 9 раз.

Операторы break и continue

Циклом можно управлять с помощью операторов break и continue.

Оператор break приводит к выходу из цикла или инструкции switch и передает управление
операторам, следующим за ними.

В следующем примере создаётся счётчик, значения которого должны изменяться от 1 до 99, однако оператор break прерывает цикл после 4 итераций:

Для вложенных циклов оператор break используется с меткой, с помощью которой завершается работа «меченой» инструкции. Метка позволяет выйти из любого блока кода. Метка имеет вид "имя_метки:", имя должно быть уникальным. Она ставится перед циклом или блоком инструкций, которые нужно завершить с помощью break:

Указание имени метки (без двоеточия) за ключевым словом break приводит к выходу из цикла или инструкции. Между ключевым словом break и именем метки не допускается перевод строки. Вызов break inner завершит вложенный цикл, а break outer ищет ближайший внешний цикл с такой меткой и переходит в его конец.

Оператор continue прерывает текущее выполнение цикла и переходит к выполнению следующего шага этого цикла. При этом, цикл while возвращается непосредственно к своему условию, а цикл for сначала вычисляет выражение инкремента, а затем возвращается к условию.

Рассмотрим пример:

В теле цикла инструкция if с помощью оператора (%) проверяет, является ли число четным. Если да, итерация цикла завершается до увеличения переменной num, но цикл продолжается со следующей итерации со значением i, увеличенным на единицу. Затем цикл выполняется до естественного завершения при значении i, равном 10. Переменная num подсчитывает количество итераций цикла. Окончательное значение num равно 5, а не 9, потому что четные операции инкремента пропускаются из-за оператора continue.

Оператор continue, как и break, можно использовать вместе с «помеченными» инструкциями для
возврата к конкретному месту в коде. Чаще всего это делается во вложенных циклах, например:

В этом примере для внешнего цикла for добавлена метка outer_mask. Каждый цикл включает 5 итераций, то есть инструкция num++ предположительно должна быть выполнена 25 раз, после чего переменная num должна быть равна 25. Оператор continue завершает выполнение внутреннего цикла, начиная новую итерацию внешнего. Она выполняется, когда j равно 3, то есть пропускаются две итерации внутреннего цикла, из-за чего num в итоге имеет значение 23.


Задачи

  • Число «задом наперед»

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

    Показать решение

    Решение:

    1. Найдем остаток от деления на 10 исходного числа num1. Получим его последнюю цифру digit.
    2. Добавим эту цифру к новому числу num2.
    3. Разделим нацело на 10 исходное число num1 и округлим до целых. Тем самым избавимся от последней цифры в нем. Полученное число сохраним в num1.
    4. Снова найдем остаток от деления на 10 того, что осталось от первого числа num1. Запомним эту цифру.
    5. Умножим на 10 второе число. Тем самым увеличим его разрядность до двух и сдвинем первую цифру в разряд десятков.
    6. Добавим к полученному второму числу запомненную ранее цифру digit из первого числа.
    7. Будем повторять перечисленные действия пока исходное число не уменьшится до нуля, т.е. пока не избавимся от всех его разрядов.
  • Сумма свойств объекта

    Есть объект users в которм перечислен возраст участников. Напишите код, который выведет суммарный возраст всех участников. Решите задачу через цикл for…in.

    
    var users = {
      "John": 28,
      "Mark": 30,
      "David": 25,
      "Richard": 42
    };
    
    /* ...ваш код... */
    

    Показать решение

  • Найти сумму четных цифр числа

    Пользователь вводит натуральное число. Найти сумму четных цифр, входящих в его состав.

    Показать решение

    Решение:

    1. В переменную sum будем суммировать все четные числа.
    2. Пока значение введенного числа (n) больше нуля выполнять пункты 3 – 5.
    3. Извлекать последнюю цифру числа (n) (путем нахождения остатка от деления на 10) и проверять ее на четность (путем нахождения остатка от деления на 2).
    4. Если цифра четная, то добавлять ее к sum.
    5. Избавиться от последней цифры числа путем ее деления нацело на 10.
    6. Вывести значение sum в консоль. Перейдите во вкладку Console инструментов разработчика ( Ctrl+Shift+J / Cmd+Shift+J ).
  • Повторять цикл, пока пользователь не введёт 0

    Напишите цикл, который предлагает prompt ввести число. Если посетитель ввёл число – попросить ввести ещё раз, и так далее.
    Цикл должен спрашивать ввести число пока либо посетитель не введёт 0, либо не нажмёт кнопку Cancel (ESC). После ввода нуля, показать на экран количество чисел, которые были введены, их общую сумму и среднее арифметическое.

  • Сумма нечётных чисел в диапазоне

    Необходимо суммировать все нечётные целые числа в диапазоне, который введёт пользователь с клавиатуры.

  • Равнобедренный треугольник из символов

    Нарисовать равнобедренный треугольник из символов *. Высоту выбирает пользователь. Например, при высоте = 6, на экране треугольник должен выглядеть так:

    Равнобедренный треугольник

  • Найти наибольшую цифру натурального числа

    Пользователь вводит с клавиатуры натуральное число. Найдите его наибольшую цифру и выведите её через alert.
    Например, введено число 987560. Наибольшая цифра в нем 9.

    Показать решение

    Решение:

    1. Переменная n – заданное число, а переменная m – максимальная цифра в этом числе.
    2. Допустим, что последняя цифра числа и есть максимальная. Извлечем ее используя оператор нахождения остатка при делении на 10. Присвоим значение переменной m.
    3. Избавимся от последней цифры с помощью операции деления на 10 и округления при помощи побитового оператора.
    4. Далее в цикле будем извлекать с конца числа поочерёдно каждую его цифру и сравнивать со значением m. Если очередная цифра будет больше, чем максимальное значение, то будем присваивать ее переменной m.
    5. Также в цикле будем каждый раз избавляться от последней, уже учтенной, цифры. Цикл завершит свою работу, когда переменная n станет равной нулю, т. е. после того, когда будут перебраны все цифры числа.
    6. В конце кода через alert выведем значение m на экран. Это и будет наибольшая цифра введенного числа.

Цикл с заданным условием продолжения работы (предусловием) записывается с помощью оператора «while». В переводе с английского while — до тех пор, пока.

Общий вид оператора:

Screenshot_10.png

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

Цикл выполняется до тех пор, пока выполняется условие, как только условие стало ложным цикл заканчивается.

Напишем программу, которая будет выводить на экран первые (10) целых чисел на экран.

Screenshot_11.png

Цикл с заданным условием окончания работы (цикл с постусловием) записывается с помощью оператора «repeat».

Общий вид оператора:

Screenshot_12.png

После слова repeat записывается тело цикла, и оно выполняется до тех пор, пока условие ложно.

Теги: Си циклы. C loops. Цикл с постусловием. Цикл с предусловием. Цикл со сщётчиком. while. do while. for. break. continue

Введение. Циклы с предусловием.

При решении практических задач постоянно возникает необходимость в повторении действия заданное количество раз, или до достижения какого-либо условия. Например, вывести список всех пользователей, замостить плоскость текстурой, провести вычисления над каждым элементом массива данных и т.п.
В си для этих целей используются три вида циклов: с предусловием, постусловием и цикл for со счётчиком (хотя, это условное название, потому что счётчика может и не быть).

Любой цикл состоит из тела и проверки условия, при котором этот цикл должен быть прекращён. Тело цикла — это тот набор инструкций, который необходимо повторять. Каждое повторение цикла называют итерацией.

Рассмотрим цикл с предусловием.

int i = 0;

while (i < 10) {
	printf("%dn", i);
	i++;
}

Этот цикл выполняется до тех пор, пока истинно условие, заданное после ключевого слова while.
Тело цикла — это две строки, одна выводит число, вторая изменяет его.
Очевидно, что этот цикл будет выполнен 10 раз и выведет на экран
0
1
2
3
и так далее до 9.

Очень важно, чтобы условие выхода из цикла когда-нибудь выполнилось, иначе произойдёт зацикливание, и программа не завершится.
К примеру

int i = 0;

while (i < 10) {
	printf("%dn", i);
}

В этом цикле не изменяется переменная i, которая служит для определения условия останова, поэтому цикл не завершится.

int i = 0;

while (i > 0) {
	printf("%dn", i);
	i++;
}

В этой программе цикл, конечно, завершится, но из-за неправильного действия он будет выполнен гораздо больше 10 раз. Так как си не следит за переполнением переменной, нужно будет ждать, пока переменная переполнится и станет меньше нуля.

int i;

while (i < 10) {
	printf("%dn", i);
	i++;
}

У этого примера неопределённое поведение. Так как переменная i заранее не инициализирована, то она хранит мусор, заранее неизвестное значение. При различном содержимом переменной i будет меняться поведение.

Если тело цикла while содержит один оператор, то фигурные скобки можно опустить.

int i = 0;

while (i < 10)
	printf("%dn", i++);

Здесь мы инкрементируем переменную i при вызове функции printf.
Следует избегать такого стиля кодирования. Отсутствие фигурных скобок, особенно в начале обучения, может приводить к ошибкам. Кроме того, код читается хуже, да и лишние скобки не сильно раздувают листинги.

Циклы с постусловием.

Цикл с постусловием отличается от цикла while тем, что условие в нём проверяется после выполнения цикла, то есть этот цикл будет повторён как минимум один раз (в отличие от цикла while, который может вообще не выполняться). Синтаксис цикла

do {
	тело цикла
} while(условие);

Предыдущий пример с использованием цикла do будет выглядеть как

int i = 0;

do {
	printf("%dn", i);
	i++;
} while(i < 10);

Давайте рассмотрим пример использования цикла с постусловием и предусловием. Пусть нам необходимо проинтегрировать функцию.

Численное интегрирование функции

Рис. 1 Численное интегрирование функции

a

b

f

x

d
x

Интеграл — это сумма бесконечно малых. Мы можем представить интеграл как сумму, а бесконечно малые значения просто заменить маленькими значениями.


a

b

f

x

d
x

=

i
=
a

b

f

i

h

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

Численное интегрирование функции методом<br/> левых прямоугольников

Рис. 2 Численное интегрирование функции методом
левых прямоугольников

Пусть искомой функцией будет

x
2

.
Нам понадобятся следующие переменные. Во-первых, аккумулятор sum для хранения интеграла. Во-вторых, левая и правая границы a и b, в третьих — шаг h. Также нам понадобится текущее значение аргумента функции x.

Для нахождения интеграла необходимо пройти от a до b с некоторым шагом h, и прибавлять к сумме площадь прямоугольника со сторонами f(x) и h.

#include<conio.h>
#include<stdio.h>

int main() {
	double sum = 0.0;
	double a = 0.0;
	double b = 1.0;
	double h = 0.01;
	double x = a;
	
	while (x < b) {
		sum += x*x * h;
		x += h;
	}
	
	printf("%.3f", sum);
	getch();
}

Программа выводит 0.328.

Решение


0

1

x
2

d
x

=

x
3

3

|
0

1

=

1

3


0.333

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

while (x < b) {
	x += h;
	sum += x*x * h;
}

Численное интегрирование функции методом<br/> правых прямоугольников

Рис. 3 Численное интегрирование функции методом
правых прямоугольников

Сумма в этом случае будет равна 0.338. Метод левых и правых прямоугольников не очень точен. Мы фактически аппроксимировали (приблизили) гладкий график монотонно возрастающей функции гистограммой.
Если немного подумать, то аппроксимацию можно проводить не только суммируя прямоугольники, но и суммируя трапеции.

Численное интегрирование функции методом<br/> трапеций

Рис. 4 Численное интегрирование функции методом
трапеций

Приближение с помощью трапеций на самом деле является кусочной аппроксимацией кривыми первого порядка (ax+b). Мы соединяем точки на графике с помощью отрезков. Можно усложнить,
соединяя точки не отрезками, а кусками параболы, тогда это будет метод Симпсона. Если ещё усложнить, то придём к сплайн интерполяции, но это уже другой, очень долгий разговор.

Вернёмся к нашим баранам. Рассмотрим 4 цикла.

int i = 0;
while ( i++ < 3 ) {
	printf("%d ", i);
}
int i = 0;
while ( ++i < 3 ) {
	printf("%d ", i);
}
int i = 0;
do {
	printf("%d ", i);
} while(i++ < 3);
int i = 0;
do {
	printf("%d ", i);
} while(++i < 3);

Если выполнить эти примеры, то будет видно, что циклы выполняются от двух, до четырёх раз. На это стоит обратить внимание, потому что неверное изменение счётчика цикла часто приводит к ошибкам.

Часто случается, что нам необходимо выйти из цикла, не дожидаясь, пока будет поднят какой-то флаг, или значение переменной изменится. Для этих целей служит оператор break, который заставляет программу выйти из текущего цикла.

Давайте решим простую задачу. Пользователь вводит числа до тех пор, пока не будет введено число 0, после этого выводит самое большое из введённых.
Здесь есть одна загвоздка. Сколько чисел введёт пользователь не известно. Поэтому мы создадим бесконечный цикл, а выходить из него будем с помощью оператора break. Внутри цикла мы будем получать от пользователя данные и выбирать максимальное число.

#include<conio.h>
#include<stdio.h>

int main() {
	int num = 0;
	int max = num;
	
	printf("To quit, enter 0n");
	/*бесконечный цикл*/
	while (1) {
		printf("Please, enter number: ");
		scanf("%d", &num);
		/*условие выхода из цикла*/
		if (num == 0) {
			break;
		}
		if (num > max) {
			max = num;
		}
	}
	
	printf("max number was %d", max);
	getch();
}

Напомню, что в си нет специального булевого типа. Вместо него используются числа. Ноль — это ложь, все остальные значения – это истина.
Цикл while(1) будет выполняться бесконечно. Единственной точкой выхода из него является условие

if (num == 0)

В этом случае мы выходим из цикла с помощью break;
Для начала в качестве максимального задаём 0. Пользователь вводит число, после чего мы проверяем, ноль это или нет. Если это не ноль, то сравниваем его с текущим максимальным.

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

Когда нам необходимо пропустить тело цикла, но при этом продолжить выполнение цикла, используется оператор continue. Простой пример: пользователь вводит десять чисел. Найти сумму всех положительных чисел, которые он ввёл.

#include<conio.h>
#include<stdio.h>

int main() {
	int i = 0;
	int positiveCnt = 0;
	float sum = 0.0f;
	float input;

	printf("Enter 10 numbersn");
	while (i < 10) {
		i++;
		printf("%2d: ", i);
		scanf("%f", &input);

		if (input <= 0.0) {
			continue;
		}

		sum += input;
		positiveCnt++;
	}

	printf("Sum of %d positive numbers = %f", positiveCnt, sum);
	getch();
}

Пример кажется несколько притянутым за уши, хотя в общем он отражает смысл оператора continue. В этом примере переменная positiveCnt является счётчиком положительных чисел, sum сумма, а input — временная переменная для ввода чисел.

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

do {
	printf("Please, enter number: ");
	scanf("%d", &n);
	if (n < 0 || n>100) {
		printf("bad number, try againn");
		continue;
	} else {
		break;
	}
} while (1);

Одним из самых используемых является цикл со счётчиком for. Его синтаксис

for (<инициализация>; <условие продолжения>; <изменение счётчика>){
	<тело цикла>
}

Например, выведем квадраты первых ста чисел.

int i;
for (i = 1; i < 101; i++) {
	printf("%d ", i*i);
}

Одним из замечательных моментов цикла for является то, что он может работать не только с целыми числами.

float num;
for (num = 5.3f; num > 0f; num -= 0.2) {
	printf("%.2f ", num);
}

Этот цикл выведет числа от 5.3 до 0.1.
Цикл for может не иметь некоторых «блоков» кода, например, может отсутствовать инициализация, проверка (тогда цикл становится бесконечным) или изменение счётчика.
Вот пример с интегралом, реализованный с применением счётчика for

#include<conio.h>
#include<stdio.h>

int main() {
	double sum = 0.0;
	double a = 0.0;
	double b = 1.0;
	double h = 0.01;
	double x;
	
	for (x = a; x < b; x += h) {
		sum += x*x * h;
	}
	
	printf("%.3f", sum);
	getch();
}

Давайте рассмотрим кусок кода

double x ;

for (x = a; x < b; x += h) {
	sum += x*x * h;
}

Его можно изменить так

double x = a;

for (; x < b; x+=h) {
	sum += x*x*h;
}

Более того, используя оператор break, можно убрать условие и написать

double x;
for (x = a;; x += h){
	if (x>b){
		break;
	}
	sum += x*x*h;
}

или так

double x = a;
for (;;){
	if (x > b){
		break;
	}
	sum += x*x*h;
	x += h;
}

кроме того, используя оператор «,», можно часть действий перенести

double x ;
for (x = a; x < b; x += h, sum += x*x*h) ;

ЗАМЕЧАНИЕ: несмотря на то, что так можно делать, пожалуйста, не делайте так! Это ухудшает читаемость кода и приводит к трудноуловимым ошибкам.

Давайте решим какую-нибудь практическую задачу посложнее.
Пусть у нас имеется функция f(x). Найдём максимум её производной на отрезке.
Как найти производную функции численно? Очевидно, по определению). Производная функции в точке — это тангенс угла наклона касательной.

Численное дифференцирование функции

Рис. 5 Численное дифференцирование функции
f

x

=

d
x

d
y

Возьмём точку на кривой с координатами (x; f(x)), сдвинемся на шаг h вперёд, получим точку (x+h, f(x+h)), тогда производная будет

d
x

d
y

=

f

(
x
+
h
)

f

x

(
x
+
h

x
)

=
tg

α

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

d
x

d
y

=

f

x


f

(
x

h
)

h

=
tg

β

Возьмём среднее от этих двух значений, получим

f

(
x
+
h
)

f

(
x

h
)

2h

В общем-то теперь задача становится тривиальной: идём от точки a до точки b и находим минимальное значение производной, а также точку, в которой производная принимает это значение.
Для решения нам понадобятся, как и в задаче с интегралом, переменные для границ области поиска a и b, текущее значение x и шаг h.
Кроме того, необходимо максимальное значение maxVal и координата maxX этого максимального значения.
Для работы возьмём функцию

x

sin

x

#include<conio.h>
#include<math.h>
#include<stdio.h>

int main() {
	double a      = 0;
	double b      = 3.0;
	double h      = 0.001;
	double h2     = h * 2.0;
	double maxVal = a*sin(a);
	double maxX   = a;
	double curVal;
	double x;

	// Проходим по всей области от a до b
	// и ищем максимум первой производной
	// Используем функцию x*sin(x)
	for (x = a; x < b; x += h) {
		curVal = ( (x+h)*sin(x+h)-(x-h)*sin(x-h) )/h2;
		if (curVal > maxVal) {
			maxVal = curVal;
			maxX = x;
		}
	}

	printf("max value = %.3f at %.3f", maxVal, maxX);
	getch();
}

На выходе программа выдаёт
max value = 1.391 at 1.077

График производной функции x*sin(x)

Рис. 6 График производной функции x*sin(x)

Численное решение даёт такие же (с точностью до погрешности) результаты, что и наша программа.

Вложенные циклы

Рассмотрим пример, где циклы вложены друг в друга. Выведем таблицу умножения.

#include<conio.h>
#include<math.h>
#include<stdio.h>

int main() {
	int i, j;

	// Для каждого i
	for (i = 1; i < 11; i++) {
		// Выводим строку из произведения i на j
		for (j = 1; j < 11; j++) {
			printf("%4d", i*j);
		}
		// После чего переходим на новую строку
		printf("n");
	}

	getch();
}

В этом примере в первый цикл по переменной i вложен второй цикл по переменной j. Последовательность действий такая: сначала мы входим в цикл по i, после этого для текущего i 10 раз подряд осуществляется вывод чисел. После этого необходимо перейти на новую строку.
Теперь давайте выведем только элементы под главной диагональю

for (i = 1; i < 11; i++) {
	for (j = 1; j < 11; j++) {
		if (j > i) {
			break;
		}
		printf("%4d", i*j);
	}
	printf("n");
}

Как вы видите, оператор break позволяет выйти только из текущего цикла. Этот пример может быть переписан следующим образом

for (i = 1; i < 11; i++) {
	for (j = 1; j <= i; j++) {
		printf("%4d", i*j);
	}
	printf("n");
}

В данном случае мы используем во вложенном цикле счётчик первого цикла.

Q&A

Всё ещё не понятно? – пиши вопросы на ящик email

Логические операторы

Циклы

Здравствуйте, дорогие читатели! Вот мы с вами и подошли к изучению циклов. Циклы в Паскаль. Что это такое? Как этим пользоваться? Для чего они нужны? Именно на эти вопросы я сегодня и отвечу.
Если вы читали этот урок, то знаете, что существует три вида алгоритмов: линейный, разветвляющийся и циклический. Мы с вами уже знаем, как реализовывать линейные и разветвляющиеся алгоритмы на Паскале. Приступим к изучению последнего типа алгоритмов.
В языке Pascal, как и в большинстве языков программирования, существует три типа циклических конструкций.

Циклы

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

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

Задача 1. Вывести все числа от 1 до числа, введенного с клавиатуры.

Как вы, наверное, уже поняли из названия, while — это цикл, в котором условие стоит перед телом. Причем тело цикла выполняется тогда и только тогда, когда условие true; как только условие становится false, выполнение цикла прекращается.

While имеет формат:

while < условие> do <оператор 1>;  {Пока … делай ….}

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

Решение задачи.

program example_while; 

var
  i, N: integer; { объявляем переменные }

begin
  i := 1; { Присваиваем i значение 1 }
  readln(N); { Считываем последнее число }
  while i <= N do {Как только i станет больше N, цикл прекратится (можно было бы написать просто <, но пришлось бы добавлять 1 к N) }
  begin {Открываем операторные скобки}
    write(i, ' '); {Выводим i}
    Inc(i);  {увеличиваем i на один.}
  end; { закрываем скобки }
end.

Repeat, или цикл с постусловием

Repeat  — полная противоположность while. Repeat — это цикл, в котором условие стоит после тела. Причем оно выполняется тогда и только тогда, когда результат условия false; как только логическое выражение становится true, выполнение цикла прекращается.

Repeat имеет формат:

repeat { повторяй … }
<оператор 1>;
< оператор 2>;

until {до…} <условие>

Begin и end не требуются.

Решение задачи.

program example_repeat;

var
  i, N: integer;{ объявляем переменные }

begin
  i := 1; { Присваиваем i значение 1 }
  readln(N); { Считываем последнее число }
  repeat {после repeat не требуется begin и end }
    write(i, ' '); {Выводим i}
    Inc(i);  {увеличиваем i на один.}
  until i = N + 1; {Например, i = 11, а N = 10. Цикл прекратится, так условие стало true.}
end.

For, или цикл с параметром

For — это  цикл, в котором тело выполняется заданное количество раз.

Существует две формы записи этого цикла:

Первая форма

for <счетчик1> := <значение1> to <конечное_значение> do <оператор1>;

После каждой итерации значение <счетчик1> будет увеличиваться на 1.

<значение1> — это начальное значение счетчика. Это может быть переменная или число.
<конечное_значение> : как только значение <счетчик1> станет больше <конечное_значение>, выполнение цикла прекратится.

Если требуется написать несколько операторов в теле цикла, используем begin и end.

И <счетчик1>, и <конечное_значение>, и <значение1> —  переменные целого типа.

Чаще всего в качестве счетчика используется переменная i.

Вторая форма

for <счетчик2> := <значение2> downto <конечное_значение> do <оператор1>;

После каждой итерации значение <счетчик2> будет уменьшатся на 1.

<значение2> — это начальное значение счетчика.
<конечное_значение> : как только значение <счетчик2> станет меньше <конечное_значение>, выполнение цикла прекратится.

Два важных примечания:

  1. Цикл повторяется, пока значение значение счетчика лежит в отрезке [значение ; конечное_значение].
  2. Изменять значение счетчика внутри тела нельзя!  Вот что выводит компилятор:

for

Решение задачи:

 
program example_for;

var
  i, N: integer;

begin
  read(N); {предположим, что мы ввели 10}
  for i := 1 to N do write(i, ' '); {количество итераций - 10 - 1 + 1 = 10}
end.

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

Давайте решим пару задач.

For1. Даны целые числа K и N  (N > 0). Вывести N раз число K.

Организовываем простой цикл от 1 до требуемого числа.

program for1;

var
  K, N, i: integer;

begin
  read(K, N);
  for i := 1 to N do write(K, ' '); {Пишем К через пробел }
end.

For2. Даны два целых числа A и B (A < B). Вывести в порядке возрастания все целые числа, расположенные между A и B (включая сами числа A и B), а также количество N этих чисел.

Так как A < B, то цикл должен будет выводить все числа от А до B. Чтобы сосчитать количество чисел, используем формулу: <конечное_значение> — <начальное_значение> + 1.

program for2;

var
  A, B, i, count: integer;

begin
  read(A, B);
  for i := A to B do write(i, ' '); {выписываем числа от меньшего к большему}
  count := B - A + 1; {считаем количество чисел}
  writeln;
  write( 'Количество чисел - ', count);
end.

For9. Даны два целых числа A и B (A < B). Найти сумму квадратов всех целых чисел от A до B включительно.

Организовываем такой же цикл, как и в предыдущей задаче, но одновременно суммируем квадраты всех чисел. Чтобы высчитать квадрат, используем функцию Sqr.

program for9;

var
  A, B, i, S: integer;

begin
  read(A, B);
  S := 0; {PascalABC делает это автоматически, но если у вас другой компилятор советуем обнулять переменные вручную}
  for i := A to B do S := S + Sqr(i);  {складываем все квадраты}
  writeln;
  write( 'Сумма квадратов - ', S);
end.

For13°. Дано целое число N (> 0). Найти значение выражения 1.1 – 1.2 + 1.3 – … (N слагаемых, знаки чередуются). Условный оператор не использовать.

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

program for13;

var
  N, A, i: integer;
  S: real;

begin
  Write('N = ');
  readln(N); 
  S := 1.1; 
  A := 1; {Сначала положительное}
  for i := 2 to N do {первую итерацию цикла мы уже произвели, поэтому начинаем отсчет с 2}
  begin 
   A := -A; {Теперь отрицательное}
   S := S + A * (1 + i / 10);  {Складываем}
  end;
  Writeln(S:5:1); {Отдадим под дробную часть одно знакоместо}
end.

While1°. Даны положительные числа A и B (A > B). На отрезке длины A размещено максимально возможное количество отрезков длины B (без наложений). Не используя операции умножения и деления, найти длину незанятой части отрезка A.

Каждый раз вычитаем B из А, пока А — В  >= 0.

program while1;

var
  A, B: integer;

begin
  readln(A, B);
  while (A - B) >=  0 do A := A - B; {Пока разница положительная, вычитаем. Необходимо предусмотреть вариант с кратностью А и B, поэтому >=}
  write(A);
end.

While4°. Дано целое число N (> 0). Если оно является степенью числа 3, то вывести True, если не является — вывести False.

Действуем следующим образом: пока N делится нацело на три, делим N нацело. Затем, если N = 1 — число является степенью тройки; если N <> 1, тогда число — не степень тройки. Для того чтобы решить эту задачу, требуется знать, что такое div и   mod,  и как работают логические выражения.

program while4;

var
  N: integer;

begin
  readln(N);
  while N mod 3 = 0 do N := N div 3; {Пока остаток от деления на три равен нулю, делим N нацело } 
  writeln(N = 1); {логическое выражение}
end.

На сегодня все! Не забывайте почаще заходить на наш сайт и кликать по кнопочкам, которые расположены перед комментариями.

Цикл
— это последовательность операторов,
которая может выполняться более одного
раза. В языке Паскаль разработано три
механизма для конструирования циклов,
использующих операторы FOR,
WHILE,
REPEAT.

Оператор
безусловного перехода

Иногда
его называют просто оператором перехода.
Он имеет вид GOTO
<Метка>,
где метка это идентификатор, описанный
в разделе LABEL.
Метка ставится перед оператором, на
выполнение которого нужно передать
управление и отделяется от него
двоеточием. Использование оператора
GOTO
в Паскале сильно ограничено и не
рекомендуется. Так, нельзя входить извне
в такие сложные операторы как IF,
CASE,
FOR,
WHILE,
REPEAT,
BEGIN
END,
процедуры, функции и другие, хотя
транслятор может и не обнаружить ошибки.
Переходы рекомендуется осуществлять
внутри одного уровня или при выходе на
более высокий уровень.

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

Пример
14.
Вычислить:

.

Вычисления
закончить при выполнении условия |Y
— 0,5
|<EPS.

Алгоритм
программы, в которой предполагается
использование операторов безусловного
перехода GOTO,
с помощью структурограмм представить
невозможно. Для графического
отображения
таких программ используют только
блок-схемы. В блок-схеме оператору GOTO
<метка>
соответствует графический объект —
стрелка. Эта стрелка передает управление
блоку, который помечен в верхнем левом
углу меткой. В нашем случае идентификатором
метки является цифра 1.

Циклический
алгоритм программы приведен на рисунке
8.
На
рисунке 8
видно,
что блок 1
повторяется
до тех пор, пока условие имеет значение
TRUE.
Как только условие станет равным FALSE,
искомая величина Y
и номер текущей итерации I
будут выведены на экран монитора.

PROGRAM
PR14;

LABEL
1;

VAR

Y,
EPS: REAL;

I:
INTEGER;

BEGIN

WRITELN(,BBEДИTE
EPS’);

READLN(EPS);

Y
:= 0;

I
:= 0;

1:
I:=I + 1;

Y:=Y
+ 1/(2*I- 1)/(2*I+ 1);

IF
ABS(Y — 0.5) >= EPS THEN GOTO 1;

WRITELN(‘I
= ‘, I,’, Y = ‘, Y:6:4)

END.

Следует
отметить, что организация циклов с
помощью операторов GOTO
не рекомендуется. Причина кроется в
том, что именно использование этого
оператора приводит к основной доле
ошибок, которые допускает программист.
Но эти ошибки, к тому же, самые трудные
в диагностике и отладке программы.
Именно для борьбы с этими ошибками
использовали такую трудоемкую процедуру,
как трассировка программы. Для борьбы
с использованием оператора GOTO
идеологами структурного программирования
были предложены так называемые
структурированные операторы циклов
FOR,
WHILE
и
REPEAT.

Циклы
с параметром. Оператор
FOR

Эти
циклы организуются в программах, где
заранее известно число повторений. При
этом повторное выполнение сопровождается
изменением управляющего параметра
(переменной цикла).

FOR
< Идентификатор параметра цикла > :=
< Выражение 1 >

{ТО
|
DOWNTO}
<Выражение 2>
DO
<Оператор>;

<Выражение
1
>
определяет первое значение параметра,
а <Выражение
2>
задает
последнее значение параметра цикла.
Параметр цикла, первое и последнее
значения могут быть только одного любого
перечисляемого типа. Напомним, что
вещественный тип к перечисляемым типам
не относится. <Выражение
1>
и
<Выражение
2>
вычисляются
один раз при вхождении в цикл и не могут
изменяться внутри цикла. Служебное
слово ТО
означает выбор следующего значения
параметра. Для множества целых чисел
выбор следующего значения тождественен
увеличению параметра на единицу (функция
SUCC(s)).
Служебное слово DOWNTO
означает выбор предыдущего значения
параметра, что для целых чисел адекватно
сложению с 1
(функция
PRED(s)).
Служебное
слово
DO
распространяется
только на один оператор (тело цикла),
следующий за ним, поэтому в качестве
этого оператора часто используется
составной оператор. Для пояснения
алгоритма работы оператора FOR
(рисунок 9), примем обозначения: I
— идентификатор параметра цикла; М
— значение выражения 1;
N
— значение выражения 2.

Итерационные
циклы

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

В
Паскале для организации итерационных
циклов предусмотрено две алгоритмические
структуры. Первая структура называется
«цикл с предусловием» и использует
оператор WHILE
DO
(рисунок 10. а). Вторая структура носит
название «цикл с постусловием» и
реализуется оператором REPEAT
UNTIL
(рисунок 10. б).

Цикл
с предусловием. Оператор

WHILE

DO

Синтаксическая
структура оператора цикла с предусловием
имеет вид:

WHILE
< Логическое выражение, или переменная
>
DO
< Оператор >;

Как
видно из блок-схемы (рисунок 10.а), перед
каждым выполнением цикла анализируется
логическое выражение или переменная.
При значении TRUE
выполняется оператор, составляющий
тело цикла. При значении FALSE
управление передается следующему за
циклом оператору. Если условие ложно с
самого начала, то оператор не выполняется
ни разу.

Цикл
с постусловием. Оператор

REPEAT
UNTIL

Недостатком
оператора WHILE
является то, что в цикле можно выполнить
только один оператор, поэтому приходится
в большинстве случаев использовать
операторные скобки BEGINEND.
Этого недостатка лишен оператор цикла
с постусловием (иногда его называют
оператором «повтора», рисунок 10. б),
имеющим следующий вид:

REPEAT

<Оператор
1>;

<Оператор
2>
;

<
Оператор К>

UNTIL
<Условие>;

Ключевые
слова REPEAT
и UNTIL
этого оператора играют роль
операторных
скобок BEGIN
END.
Поэтому эта конструкция тоже один
оператор.

Break,
Continue

ВциклахFOR,
REPEAT,
WHILE
можно использовать процедуры BREAK
и CONTINUE.
Первая процедура позволяет досрочно
выйти из цикла, не дожидаясь выполнения
условий выхода. Вторая процедура
позволяет начать новую итерацию цикла
даже в том случае, если предыдущая
итерация не завершена. Использование
этих процедур ускоряет работу программы
в рамках принципа структурного
программирования.

Обозначение циклов на блок-схемах
согласно ГОСТу

ГОСТом предусмотрен единый блок для
обозначения различных циклов (Рисунок
11). В блоке, соответствующем началу цикла
указывается имя цикла (Как правило, это
одна буква латинского алфавита) и
начальное значение переменной цикла.
В зависимости от оператора цикла, условие
окончания записывается либо в блоке,
соответствующем началу цикла (для
операторов FOR…DOиWHILE…DO),
либо в блоке, соответствующем концу
цикла (для оператораREPEAT…UNTIL).
Аналогично записывается и шаг изменения
переменной цикла.

Примеры использования различных
операторов цикла

Пример 15.

Вычислить сумму:

.

Значения величин A,B,m,nввести
с клавиатуры. Алгоритм решения данной
задачи описывается с помощью следующей
структурограммы:

Ввод с клавиатуры A,B,m,n;S:=0;

Для IотMдоNcшагом
+1 делать:

S=S+I2/(N+I);

Вывод на экран значение (A+B*S).

PROGRAM
PR15;

VAR

А,
X, S: REAL;

I,
М,
N: INTEGER;

BEGIN

WRITELN(‘BBEДИTE
A, B, M
и
N’);

READLN(A,
B, M, N);

S:=0;

FOR
I:=M TO N

DO
S:=S + I*I/(N + I);

WRITELN(‘S
= ‘, A+B*S:6:4)

END.

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

  • Оператор
    END
    начинать с той же позиции, что и
    соответствующий ему оператор BEGIN.
    Это удобно в тех случаях, когда в
    программе используются вложенные
    составные операторы.

  • Оператор
    DO
    писать под соответствующим оператором
    FOR.

  • Операторы
    THEN
    и ELSE
    писать под соответствующим оператором
    IF.

Пример
16.

Найти
сумму S
всех целых чисел, кратных 3 на отрезке
[М,
N].

Эта
задача похожа на предыдущую. Отличие
состоит в том, что, просматривая все
числа из интервала [М,
N],
мы должны проверить, делится ли число
I
без остатка на 3 прежде, чем его суммировать
к S.
Для проверки деления используется
операция mod
деление
с остатком целых чисел. Таким образом,
условие деления числа I
на 3 без остатка будет иметь вид: I
mod
3
=
0.

Алгоритм
решения этой задачи отличен от предыдущего
наличием условия в теле
арифметического
цикла и описан с помощью приведенной
ниже структурограммы.

PROGRAM
PR16;

VAR
X, S: REAL;

I,
M, N: INTEGER;

BEGIN

WRITELN(‘BBEДИTE
M
И
N’);

READLN(M,
N);

S:=0;

FOR
I:=M TO N

DO
IF I MOD 3 = 0

THEN
S := S + I;

WRITELN(‘S=’,
S:6:4)

END.

Табулирование
функции

Задача
табулирования функции предполагает
получение таблицы значений функции при
изменении аргумента с фиксированным
шагом. В качестве исходной информации
должны быть заданы: Х0,
Х
n
– начало и конец промежутка табулирования,
при этом (Х0<
Х
n);
n
– число шагов разбиения промежутка
[Х0,
Xn];
F(X)
– описание табулируемой функции.

При
составлении алгоритма предполагается,
что X
– текущее значение аргумента; h
– шаг изменения аргумента (иногда его
называют шагом табуляции функции); i
– текущий номер точки, в которой
вычисляются функция (i
= 0 ..
n).

Количество
интервалов n,
шаг табуляции h
и величины Х0,
Х
n
связаны между собой формулой:

Интерпретация
переменных (т. е. их обозначение в
математической постановке задачи, смысл
и тип, обозначения в блоксхеме и программе)
приведена в таблице имен.

Таблица
имен

Математ.
величина

Обозначение
в
программе

Содержательный
смысл

Тип
переменной

n

N

Число
интервалов разбиения [Хо, Хn]

integer

Х0

Х0

Начало
промежутка

real

Хn

XN

Конец
промежутка

real

X

X

Текущее
значение аргумента

real

F(X)

Y

Текущее
значение функции

real

h

Н

Шаг
табулирования

real

Пример
17.

Табулировать
функцию F(X)
в N
равноотстоящих точках, заданную на
промежутке [Х0,
Xn],
где

PROGRAM
PR17;

VAR

I,
N: INTEGER;

X,
Y: REAL;

H,
X0, XN: REAL;

BEGIN

WRITELN(‘ВВЕДИТЕ
X0, XN, N’);

READLN(X0,
XN, N);

H
:= (XN — X0)/N;

FOR
I:=0 TO N

DO
BEGIN

Y:=
SIN(X+1)*EXP(2-X*X);

X
:= X0 + I * H;

WRITELN
(X:4:1,»,Y:9:6)

END

END.

Теперь
запишем решение этой же задачи, но с
использованием циклаWhileDO.

PROGRAM
PR17_while;

VAR

N:
INTEGER;

X,
Y: REAL;

H,
X0, XN: REAL;

BEGIN

WRITELN(‘ВВЕДИТЕ
X0, XN, N’);

READLN(X0,
XN, N);

H
:= (XN — X0)/N;

X:=X0;

WHILE
X<=XN

DO
BEGIN

Y:=
SIN(X+1)*EXP(2-X*X);

X
:= X + H;

WRITELN
(X:4:1,»,Y:9:6)

END

END.

Арифметический
цикл с рекуррентной зависимостью

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

В
этой рекуррентной формуле для вычисления
i
-го члена последовательности Yi,
где i
>
k,
используются k
предыдущих членов последовательности

.
Для вычислений по этой формуле нужно
задать k
первых членов последовательности –
.

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

Пример
18
.

Вычислить
значение tgx:

Знаменатель
формулы для вычисления tgX
представляет собой цепную дробь. Для
вычисления такого знаменателя в цикле
удобно использовать рекуррентную
зависимость с памятью в один член
последовательности Аi=
F(Ai-1).
Для вывода рекуррентной формулы следует
использовать таблицу 18.

Таблица 18

Номер 1

Член
последовательности

Величина

0

A0

1

1

A1

2

A2

3

A3

4

A4

5

A5

Из
таблицы 23 видно, что рекуррентная формула
принимает вид:

PROGRAM
PR18;

VAR

X,
A: REAL;

I:
INTEGER;

BEGIN

WRITELN(‘BBEДИTE
X’);

READLN(X);

A
:=
1;

FOR
I := 1 TO 5

DO
A := 11 — 2 * I — X * X/A;

WRITELN(‘tgX
= ‘, X/A:8:5)

END.

Пример
19.

Пользуясь
рекуррентной формулой, для заданного
N
вычислить
,
известны Y0,
Y1,
Y2,
a
Yi(i≥3)
вычисляется по формуле:

.

Таблица
имен

Математ.
величина

Обозначение
в
программе

Содержательный
смысл

Тип
переменной

N

N

Номер
последнего члена последовательности
SN

integer

Y0,
Yi-3

Y3

Член
последовательности с номером i-3

real

Y1,
Yi-2

Y2

Член
последовательности с номером i-2

real

Y2,
Yi-1

YI

Член
последовательности с номером i-1

real

Yi

Y

Член
последовательности с номером
i

real

SN

S

Искомая
сумма

real

Первым
шагом в работе алгоритма является ввод
данных Y0,
Y1,
Y2,
N. При вводе трех первых значений
последовательности нужно использовать
рабочие ячейки Y3,
Y2
и Y1
соответственно. На втором шаге требуется
проанализировать значение N.
Если N
< 3
,
то рекуррентная формула
для подсчетаS
суммы первых N
членов не потребуется. Для определения
S
при условии N
< 3

в алгоритме предусмотрен переключатель
(оператор CASE),
имеющий три ветви: N
= 0, N = 1

и «В противном случае», куда попадает
и случай N
= 2
.
Для каждой ветви подсчитывается
соответствующая сумма S.
Третий шаг выполняется только в том
случае, если N
> 2
.
На этом шаге для I
от 3
до N
по рекуррентной формуле вычисляются
Y,
и подсчитывается их сумма S.
Найденное значение S
на последнем четвертом шаге выводится
на экран.

PROGRAM
PR19;

VAR

Y3,
Y2, Yl, Y, S: REAL;

I,
N: INTEGER;

BEGIN

WRITELN(‘ВВЕДИТЕ
Y0, Yl, Y2, N’);

READLN(Y3,
Y2, Yl, N);

CASE
N OF

0:
S := Y3;

1:
S := Y3 +Y2

ELSE
S := Y3 + Y2 + Y1

END;
{CASE}

IF
N > 2

THEN
FOR I := 3 TO N

DO
BEGIN

Y
:= LN(ABS(Y1*Y1 + Y3 + 1));

S
:= S + Y;

Y3
:= Y2;

Y2
:= Y1;

Y1
:= Y

END;

WRITELN(‘S=’,
S:10:8)

END.

Вложенный
арифметический цикл

Под
вложенным арифметическим циклом понимают
такую алгоритмическую структуру, при
которой в тело одного цикла с параметром
включен другой цикл со своим параметром.
Другими словами составная инструкция:

FOR
I :=…

DO
FOR
J:=…

DO

является
признаком вложенного арифметического
цикла.

Пример
20.

Вычислить

Для
решения этой задачи необходима
дополнительная переменная, как иногда
говорят, рабочая ячейка R
для накопления в процессе вычисления
S
вложенной суммы:

PROGRAM
PR20;

VAR

R,
S: REAL;

К,
P: INTEGER;

BEGIN

S:=0;

FOR
K:=1 TO 10

DO
BEGIN

R:=0;

FOR
P:=1 T0 15

DO
R := R + SQR(K — P);

S:=S
+ K*K*K*R

END;

WRITELN(‘S=’,
S:10:8)

END.

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

Пример
21.

Используя
вложенный цикл, определить число
счастливых билетов S,
номера которых меняются от 000001 до 999999.

Воснове алгоритма решения этой задачи
лежит принцип десятичного счетчика,
имеющего шесть разрядов. Роль разрядов
играют индексы в следующем порядкеI,
J,
К,
L,
М, N
.
Счастливым называется такой номер, у
которого три левых разряда в сумме равны
сумме трех правых разрядов, то есть I+J
+
K
=
L
+
M
+
N.

PROGRAM
PR24;

VAR

S:
REAL;

I,
N, J, K, L, M: INTEGER;

BEGIN

S:=-l;

FOR
I := 0 TO 9

DO
FOR J:=0 TO 9

DO
FOR K:=0 TO 9

DO
FOR L:=0 TO 9

DO
FOR M:=0 TO 9

DO
FOR N:=0 TO 9

DO

IF
I+J + K = L+M + N

THEN
S:=S+ 1;

WRITELN(‘Число
счастливых
билетов =
‘,
S:6:0)
END.

В
связи с тем, что номер 000000 в катушке
билетов отсутствует, то этот номер нужно
вычесть из найденного числа. Это можно
сделать разными способами. В предложенном
алгоритме это реализовано так S
:= -1
.
Это решение логично. При исходном
состоянии счетчика: I
= 0,
J
= 0, К = 0,
L
= 0, М = 0, N = 0
,
условие I
+
J
+
K
=
L
+М + N

принимает значение TRUE,
и S
становится равным нулю S
= —
1
+ 1

=

0
.
Таким образом, все переменные приняли
исходное значение для дальнейших
расчетов.

Основным
достоинством вложенного цикла является
возможность в выражениях (в заголовке
цикла или его теле) использовать параметры
внешних циклов. Например, в описанном
выше примере, в теле цикла с параметром
N
используются
также текущие значения параметров I,
J,
К,
L,
М

внешних циклов по отношению к этому
циклу. К параметрам внутренних циклов
из внешнего цикла не должно быть
обращений. Транслятор с Паскаля такие
обращения не проверяет, но для внешних
циклов значения параметров внутренних
циклов не определено. Допускается выход
из тела цикла FOR
DO
… любого уровня вложения на любой
предыдущий
уровень до полного завершения
цикла с помощью оператора GOTO,
но не рекомендуется это делать. При
выходе из цикла (досрочном или нормальном)
значение параметра цикла становится
неопределенным. Можно непосредственно
из цикла завершить работу программы.
Для этой цели используют оператор HALT
[(Код)]
,
где код — это необязательный параметр,
представляющий собой целое число типа
WORD,
которое является кодом возврата вашего
ЕХЕ
модуля.

Пример
22.

Вычислить

.
Вычисления остановить при выполнении
условия
.

Для
решения этой задачи удобно использовать
оператор цикла с предусловием
WHILE
DO.

PROGRAM
PR2
2;

VAR

У,
Е:
REAL;

I:
INTEGER;

BEGIN

WRITELN(‘ВВЕДИТЕ
E’);

READLN(E);

I:=
1; Y:=0.5;

WHILE
I * EXP(-I * LN(2)) > E

DO
BEGIN

Y:=Y
+ I*EXP(-I*LN(2));

I:=
I+ 1;

END;

WRITELN(‘Y
=’, Y:12:8)

END.

Пример
23.

Вычислить
с точностью ε
квадратный корень из величины
.
Вычисление
проводить по рекуррентной формуле:

выбрав
в качестве начального приближения
величину

При
решении подобных задач условие остановки
вычислительного процесса
формулируется
следующим образом:
|
Yi
Yi-1
|<ε
.

Математ.
величина

Обозначение
в
программе

Содержательный
смысл

Тип
переменной

i

I

Номер
итерации

integer

Yi-1

Y1

Член
послед. У с номером i-1

real

Yi

У

Член
последовательности У с номером i

real

X

X

Величина
X, квадратный корень которой мы ищем

real

ε

Е

Требуемая
точность расчетов

real

Вводим
с клавиатуры величиныX
и Е.
Далее вычисляем первое приближение Y.
Если X<1,
то Y
принимается равным X,
в противном случае за Y
принимается величина Х/2.
Далее на основании Y
нужно найти следующее приближение.
Поэтому вычисленное значение записывается
в ячейку с именем Y1
и с этого момента времени считается
предыдущим значением. Текущее значение
Y
рассчитывается по рекуррентной формуле
на основании Y1
и X.
Этот циклический процесс повторяется
до тех пор, пока не выполнится условие
|
Y — Y1 | < Е
.
После чего Y
считается равным значению корня из X
с точностью Е
и выводится на экран монитора.

PROGRAM
PR23;

VAR

X,
Y, YI, E: REAL;

BEGIN

WRITELN(‘BBEДИTE
X, E’);

READLN(X,
E);

Y:=
X;

IF
X>= 1 THEN Y:= Y/2;

REPEAT

Y1:=Y;

Y:=
(Y1 +X/Y1)/2

UNTIL
ABS(Y-Y1)<E;

WRITELN(Y
=’, Y:12:8)

END.

Вычисление
предела последовательности

Вычисление
предела последовательности является
типичной задачей на использование
итерационного цикла.

Пример
2
4.

Последовательность
{Xn}
определена следующим образом:

Найти
предел последовательности {Xn},
принимая за него такое Хn,
при котором

|Xn

Xn-1|
<
ε.

Таблица
имен

Магемат.

величина

Обозначение

в
программе

Содержательный
смысл

Тип

переменной

n

N

Номер
итерации

integer

Xn-1

XI

Член
последовательности X с номером n-1

real

Хn

X

Член
последовательности X с номером n

real

ε

E

Требуемая
точность расчетов

real

PROGRAM
PR24;

VAR

X,
X1, E: REAL;

N:
INTEGER;

BEGIN

WRITELN(‘BBEДИTE
E’);

READLN(E);

N
:=
1;

X
:=
1;

REPEAT

X1
:= X;

X
:= ( N * N +2)/(3*N * N – N +1);

N:=N+
1;

UNTIL
ABS(X

X1)
<
E;

WRITELN(‘Предел
последовательности равен’,
X:12:8)

END.

Вычисление
суммы бесконечного ряда с использованием
рекуррентной формулы

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

Есть
определенные признаки, которые помогают
выявить наличие рекуррентных формул.
К таким признакам относятся выражения
(-1)n,
X
n,
n!
и подобные этим выражения, присутствующие
в формуле общего члена бесконечного
ряда. Часто рекуррентная формула для
бесконечного ряда находится путем
деления соседних членов ряда друг на
друга.

Пример
25.

Вычислить

.
Вычисление ряда окончить при выполнении
условия:
.

Для
решения этой задачи необходимо
использовать рекуррентную формулу. А
найти ее можно следующим способом.
Сделаем преобразование исходного ряда
в следующий вид:

Тогда
условие окончания вычислений будет
выглядеть так | Ai
| <
ε
.

Это условие либо выполнится для некоторого
i
=
n
и вычислительный процесс будет завершен,
либо не выполнится. Во втором случае
используют термин «зависание программы».
Оператор ЭВМ искусственно останавливает
программу и выясняет причину зависания:
неправильные исходные данные, например
комбинация X
и ε,
или допущена ошибка в тексте программы,
а может быть получена неправильная
рекуррентная формула, или другая причина
имеет место.

Нас
в этом примере интересует нормальный
режим работы программы, а это означает,
что существует такое n,
для которого справедливы следующие
формулы:

Эти
формулы и будут исходными для нашей
задачи. На этом первый этап подготовки
бесконечного ряда к нахождению его
суммы Y
с погрешностью ε
на компьютере завершается. Если
рекуррентную формулу найти невозможно
или нет в этом необходимости, то можно
ограничиться только приведенными выше
преобразованиями.

Но
в нашем случае нужен второй этап
преобразования, а именно, нахождение
рекуррентной формулы. Для этого поделим
два соседних члена Аi,
Аi-1
(Иногда, с точки зрения математических
преобразований проще будет разделить
Аi+1
на Аi,
что эквивалентно):

Отсюда находим рекуррентную формулу:

Таблица имен

Математ.
величина

Обозначение
в
программе

Содержательный
смысл

Тип
переменной

i

I

Номер
итерации

integer

X

X

Параметр
бесконечного ряда

real

Y

Y

Искомая
сумма

real

Ai

А

Член
последовательности А с номером i

real

ε

Е

Требуемая
точность расчетов

real

PROGRAM
PR25;

VAR

Y,
Е,
А,
X: REAL;

I:
INTEGER;

BEGIN

WRITELN(‘Введите
X, E’);

READLN(X,
E);

I:=
1;

A:=
-X*X/2;

Y:=A;

WHILE
ABS(A) >= E

DO
BEGIN

I
:= I+1;

A:=
-X*X/2/I/(2*I — 1)*A;

Y
:= Y + A;

END;

WRITELN(‘Y=’,
Y:10:6)

END.

Вложенные
итерационные циклы

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

WHILE…

DO WHILE…

DO…

WHILE…

DO REPEAT…

UNTIL…

REPEAT

REPEAT

UNTIL…

UNTIL…

REPEAT

WHILE …

DO …

UNTIL…

Пример
26.

Составить
программу для нахождения числа слов в
предложении и количества букв в самом
длинном слове.

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

Таблица
19

Идентификатор

Содержательный
смысл

Тип
переменной

А

Число
букв в новом слове

INTEGER

В

Число
букв в самом длинном слове

INTEGER

С

Число
слов

INTEGER

F

Последний
символ, введенный с клавиатуры

CHAR

В
программе используется три счетчика
А,
В, С

и переменная F
для чтения из входного файла INPUT
текущего символа (литеры). Алгоритм
содержит два итерационных цикла. Внешний
цикл с постусловием используется для
подсчета числа слов в предложении С,
а также для выявления самого длинного
слова (формирование значения переменной
В).
Внутренний цикл обеспечивает чтение
очередной литеры F,
отделяет русские буква от знаков
препинания и латинских букв, определяет
конец слова и подсчитывает количество
букв А
в текущем слове. Концом слова считается
пробел или точка.

PROGRAM
PR
26;

VAR

А,
В, С:
INTEGER;

F:
CHAR;

BEGIN

WRITELN
(‘Введите слова, разделенные пробелами.’);

WRITELN
(‘В конце предложения поставьте точку.’);

В
:= 0;

С
:= 0;

REPEAT

A
:= 0;

F
:= ‘*’;

WHILE
(F <> ») AND (F <> ‘.’) {
Конец
слова}

DO
BEGIN READ(F);

IF
((‘A'<=F) AND (F<=’
Я‘))
OR (((‘a’
оF)
AND (F<=’n’)) OR ((‘p'<=F) AND (F<=’
я‘)))

THEN
A
:=
A
+ 1

END;

С
:= С + 1; { Новое слово}

IF
В <
A
THEN
В := А

UNTIL
F=’.’; {
Конец предложения }

WRITELN
(‘Наибольшее число букв в слове =’, В);

WRITELN
(‘Число слов в предложении =’, С)

END.

В
этой программе оператор READ
использован для ввода потока символов
произвольной длины. Реализован логический
вложенный цикл, в котором применяются
как оператор постусловия REPEAT
для анализа конца предложения, так и
оператор предусловия WHILE
для выделения слов в предложении.

Понравилась статья? Поделить с друзьями:
  • Nissan patrol y61 руководство по эксплуатации скачать
  • Как клеить алмазную картину инструкция по применению
  • Виза платежная система руководство
  • Магнит руководство компании контакты
  • Днс руководство официальный сайт