Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
4 основи програмування книга.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.77 Mб
Скачать

8. Ітераційні цикли

8.1. Оператори повторення While і Repeat

У попередньому параграфі ми вивчили оператор повторення з параметром (For).

Цей оператор використовується лише у випадку, коли заздалегідь відома кількість повторень тіла циклу. У більш загальному випадку, коли кількість повторень заздалегідь невідома, а задана деяка умова закінчення (або продовження) циклу, у мові Pascal використовують інші оператори повторення: оператор циклу з передумовою While і оператор циклу з постумовою Repeat.

Оператор циклу з передумовою визначений діаграмою:

Оператор циклу

з передумовою

Оператор (тіло циклу) виконується до тих пір, поки умова істинна. Якщо при першій перевірці умова виявилась хибною, оператор не виконується ні разу.

Приклад 8.1. Знайти найменший натуральний розв’язок нерівності

x3 + ax2 + bx + c > 0

з цілими коефіцієнтами.

Очевидний алгоритм пошуку розв’язку складається у послідовному обчисленні значень Y = x3+ax2+bx+c для x = 1, 2, 3, ... до тих пір, поки Y  0.

Program UneqvSolution;

Var

a, b, c : Integer;

X : Integer;

Y : Real;

Procedure InpData (Var a, b, c : Integer);

Begin

Write(‘ введіть коефіцієнти a, b, c : ‘);

Readln(a, b, c);

End;

Procedure FindRoot (a, b, c : Integer; Var X: Integer);

Var Y : Real;

Begin

X := 1;

Y := a + b + c + 1; { Ініціалізація циклу }

While Y <= 0 do begin

X := Succ(X); { Наступне значення X }

Y := ((X + a)*X + b)*X + c { Наступне значення Y }

end;

End;

Begin

InpData (a, b, c);

FindRoot (a, b, c, X);

Writeln(‘X = ‘, X)

End.

Для обґрунтування цього методу вимагається єдине: впевнитись у тому, що цикл коли-небудь завершиться, тобто що розв’язок нерівності існує! Відмітимо, що функція Y = x3 + ax2 + bx + c є необмежено зростаючою. Тому починаючи з деякого значення х Y стане додатнім. Тому кількість повторень циклу є скінченою.

Оператор циклу з постумовою визначений діаграмою:

Оператор циклу

з постумовою

Тіло циклу Repeat виконується до тих пір, поки умова приймає значення False. Дії, що містяться в тілі циклу, будуть виконані у крайньому випадку один раз. Таким чином, умова є умовою закінчення циклу.

Приклад 8.2. Знайти номер найменшого числа Фібоначчі, що ділиться на 10. Послідовність Фібоначчі { F(n) } визначається рекурентно:

F(1) = F(2) = 1, F(n+2) = F(n+1) + F(n)

Як і у попередньому прикладі, обчислюємо Fn для n = 3, 4, ... до тих пір, поки не знайдемо елемент послідовності, що ділиться на 10. Проблема обґрунтування методу залишається тією ж: чи існує потрібний елемент?

Program Fibbonachy;

Var

Fib1, Fib2 : Integer;

Index : Integer; Buf : Integer;

Begin

Fib1 := 1;

Fib2 := 1;

Index := 2; { Ініціалізація циклу }

Repeat

Buf := Fib2;

Fib2 := Fib2 + Fib1; { Наступне число Фібоначчі }

Fib1 := Buf; { Попереднє число Фібоначчі }

Index := Succ(Index) { Номер числа Фібоначчі }

until Fib2 mod 10 = 0;

Writeln(‘Номер = ‘, Index, ‘ Число = ‘, Fib2)

End.

Цикли While і Repeat називають ще ітераційними циклами, оскільки за їх допомогою легко реалізувати різного роду ітераційні обчислення (обчислення, в яких кожний наступний результат є уточненням попереднього). Умова закінчення циклу – досягнення відхилення результату Yn от Yn-1 деякої допустимої похибки :

|Yn - Yn-1| < 

Приклад 8.3: Обчислити з заданою точністю значення кореня рівняння x = cos(x) на відрізку [0 ; 1] методом ділення відрізка навпіл .

Метод наближеного розв’язування рівняння діленням відрізка навпіл – один з найбільш простих і поширених чисельних методів. Суть його полягає у послідовному уточненні меж відрізка, на якому існує корінь. На кожному кроці методу цей відрізок ділиться навпіл, а потім вирішується питання про те, в якій половині (лівій чи правій) знаходиться корінь. Зменшення відрізка вдвоє теоретично гарантує завершення циклу пошуку з заданою точністю.

Procedure TransEquation (a, b, Epsilon : Real; Var Root: Real);

Var

u, v: Real;

Fu, Fr : Real;

Begin

u := a;

v := b; { ініціалізація циклу}

Fu := Cos(u) - u;

Repeat

Root := (u + v)/2 ; { середня точка відрізка }

Fr := Cos(Root) - Root;

if Fu*Fr > 0 { вибір правої або лівої половини }

then begin

u := Root;

Fu := Fr

end

else v := Root

until Abs(v - u) < Epsilon;

End;

Для того, щоб знайти кількість N повторень у циклі, відмітимо, що на k-тому кроці циклу виконана нерівність |v - u| = (b - a)/2k. Тому при найменшому k такому, що (b - a)/2k <  цикл завершиться. Неважко обчислити N:

N = [ log2(b - a)/ ] (1)

Як показують розглянуті приклади, одна з основних проблем аналізу програм, що містять ітераційні цикли, складається в обґрунтуванні завершення циклу (і програми). На відміну від алгоритмів з арифметичними циклами, ця проблема не є простою!

Оскільки кількість повторень ітераційного циклу не визначена, задача оцінки складності програми часто також не проста.