Калькулятор "Школьная доска 3"

Циклы while и until




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

n = n+1

Это не уравнение. Формула означает, что значение величины n, стоящей в левой части формулы, получается прибавлением 1 к  предыдущему значению этой величины, находящейся в правой части. Естественно,  в этом процессе требуется c чего-то начать. Поэтому перед циклом нужно задать начальное (инициирующее) значение величины n, положив ее, скажем, равной нулю.

В калькуляторе "Школьная доска" можно использовать два вида циклов:

Пары ключевых слов while, wend и  do, until ограничивают блок формул, называемый телом цикла. Например, цикл, о котором только что говорилось, можно организовать так:

n = 0
while(n<10)
    n = n+1
wend

Здесь тело цикла состоит из одной рекуррентной формулы n = n+1, начальное значение задается находящейся вне цикла формулой n = 0, а логическим условием является неравенство n<10. После запуска счета кнопкой "Start", к числу n на каждом шаге будет добавляться 1. И так будет продолжаться до тех пор, пока выполняется неравенство n<10. Когда это неравенство перестанет выполняться, цикл закончит свою работу, и величина n будет, естественно, равна 10.

Приведем более осмысленный пример подсчета суммы квадратов первых 10 натуральных чисел:

n = 0
S = 0
while(n<10)
    n = n+1
    S = S+n^2
wend
= S

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

Цикл do-until действует точно также, как и цикл  while-wend, но является циклом с постусловием, то есть логическое условие проверяется не до, а после выполнения тела цикла. Поэтому тело цикла в любом случае выполняется по меньшей мере один раз.  Кроме того выход из цикла происходит не при нарушении логического условия, а при его выполнении.

Совет. Какой из этих циклов использовать дело  вкуса. Иногда более удобен один, иногда другой.

Вот решение той же самой задачи о сумме квадратов первых 10 натуральных чисел  с помощью цикла do-until:

x = 0
S = 0
do
    n = n+1
    S = S+n^2
until(x>=10)

Заметим, что в отличие от предыдущего примера строка "= S" здесь не нужна. При выходе из цикла  ответ будет под формулой S = S+n^2.

Замечание. Циклов в программе может быть несколько, и они могут быть вложенными друг в друга.

Пример. Найти решение уравнения ex-3x=0 с точностью до 10-7.

Первый способ. Воспользуемся методом перемены знака. Так как при x = 0 левая часть уравнения положительна, а при x = 1 — отрицательна, то корень должен находиться в этом интервале. Поэтому вычисляем  левую часть равенства, начиная с 0 и двигаясь к 1 шагом h = 0.001. Как только ее значение изменится с положительного на отрицательное, корень будет пройден и, следовательно, определен с точностью до h. Набираем:

h = 0.001
x = 0
do
    x = x+h
    f = e^x-3*x
until(f<0)

и запускаем счет. После остановки выясняется, что перемена знака произошла при значении x=0.620. Точность при этом заведомо недостаточна, так как шаг h выбран слишком большим. Чтобы достичь заданной точности, шаг нужно было выбрать равным 10-7, но такой счет занял бы слишком много времени.

Воспользуемся тем, что проведенный расчет сузил интервал, в котором должен находиться корень уравнения.  Потому  повторим вычисления с обеспечивающим заданную точность шагом h = 10-7, выбрав в качестве начального значения последнюю известную точку, в которой функция еще положительна, то есть x = 0.619. Теперь результат удовлетворителен: перемена знака произошла при  x = 0.6190613, в которой левая часть уравнения равна -1.5158339*10-8.

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

h = 0.1
x = 0
while(h>10^-7)
    do
        x = x+h
        f = e^x-3*x
      until(f>0)
     x = x-h
     h = h/10
wend
= x

В этом листинге в качестве внутреннего цикла используется уже знакомый цикл  do-until, вычисляющий точку изменения знака левой части уравнения, а начальное условие для этого цикла и определяющий точность параметр h устанавливаются во внешнем цикле while-wend. А именно, формула x = x-h определяет  начальное значение x, а формула, следующая за ней, уменьшает шаг h в 10 раз. Условием выхода из внешнего цикла является достижение требуемой точности h < 10-7.

Второй способ. Воспользуемся методом сжимающих отображений, записав уравнение в виде x=ex/3. Набираем:

x = 0
do
    x_old = x
    x = e^x/3
until(|x-x_old|<10^-8)

Здесь в переменной x_old запоминается текущее значение x, а новое вычисляется в  формуле, идущей ниже. Условием выхода из цикла является то, что последовательные значения x_old и x отличаются лишь в 8-м знаке после нуля.

Пример. Требуется вычислить интеграл функции f(x)=sin2x на интервале от 0 до π/2 с точностью до 0.001.

Воспользуемся методом прямоугольников. Набираем:

h = 0.0001
x = 0
S = 0
while(x<pi/2)
    x = x + h
    S = S+[sin(2x)]^2*h
wend

и запускаем счет. Результат — 0.78545184. Так как этот интеграл, вычисленный аналитическими методами, равен π/4=0.78539816, то можно заключить, что шаг h был выбран правильно.  Обычно при вычислении интегралов точный результат не известен. Поэтому, выбрав какое-либо значение шага h, нужно последовательно уменьшать его, пока результат вычислений не перестанет меняться в нужном (в данном случае четвертом) знаке после 0. Этот алгоритм легко осуществить, добавив внешний цикл,  с этим условием выхода:


S = 0
do
    h = h/2
    S_old = S
    x = 0
    S = 0
    while(x<pi:2)
        x = x+h
        S = S+[sin(x)]^2*h
    wend
until(|S-S_old|<10^-4)
= S
Совет:
  • Отступы в формулах, облегчающие их восприятие, можно не делать. Они автоматически устанавливаются после первого счета.
  • Если логическое условие, фигурирующее в цикле, составлено с ошибкой, то цикл может получиться бесконечным,  то есть вычисления никогда не закончатся. Чтобы остановить калькулятор, нужно воспользоваться кнопкой "Стоп" или клавишей "Esc". После чего всплывет окно сообщений, предлагающее прекратить или продолжить счет.