в дійсне. З цієї ж причини, до речі, при виконанні readln(z) із змінною z:real можна набрати на клавіатурі не дійсну, а цілу сталу – z одержить дійсне значення. Зворотні перетворення програміст повинен задавати явно за допомогою функцій trunc або round, наприклад, b:=round(a).
Задача
3.6. Намалюйте три кола, відзначених іменами типів цілих, дійсних і бульових. Проведіть стрілки між ними – стрілка веде від кола А до кола Б, якщо означено операції з операндами типу А и значеннями типу Б, наприклад, від кола integer до кола boolean. Позначте стрілки знаками відповідних операцій. Назвіть поліморфні й неполіморфні операції.
2. Комп'ютер сам вирішить,
що робити і чого не робити
2.1. Оператори розгалуження та складений
Майже кожний, хто провчився в школі років вісім, пам'ятає, як обчислювати дійсні корені квадратного рівняння ax2+bx+c=0 (природно, за умови a? 0):
(1) прочитати коефіцієнти a, b, c;
(2) обчислити d=b2-4ac;
(3) якщо d>0, то обчислити x1=(-b- )/(2a), x2=(-b+ )/(2a);
у противному випадку
якщо d=0, то обчислити x1=-b/(2a),
інакше нічого не робити.
Майже кожний розуміє, що він задає три різні послідовності дій. Яка саме виконується, залежить від конкретних значень a, b, c. Пункт (3) алгоритму задає перевірку, яка з умов d>0, d=0 або d>0 справджується, і залежно від цього ті або інші дії.
Умову будемо розуміти як фразу, що може бути або істинною, або хибною. У мові Паскаль умову можна відтворити бульовим виразом, як правило, із змінними. Його значеннями можуть бути true або false – це залежить від значень змінних. Звичайно, умови можуть бути тотожно істинними або тотожно хибними – вони відтворюються виразами, швидше за все, без змінних. Втім, вирази z or not z і z and not z мають значення відповідно true і false незалежно від значення z.
Перевірка умови при виконанні програми – це обчислення відповідного бульового виразу.
Перевірка умов і виконання залежно від цього різних дій задається в мові Паскаль операторами розгалуження. Вони мають дві форми – повну та скорочену. Оператор розгалуження в повній формі має вигляд:
if умова then оператор else оператор
Ключові слова if, then, else – це англійські "якщо", "то", "інакше". Для полегшення читаності програми оператор розгалуження часто записують "східцями":
if умова
then
оператор
else
оператор
або
if умова then
оператор
else оператор
Виконання його полягає в тім, що спочатку обчислюється значення умови, записаної після слова if. Далі, якщо цим значенням є true, виконується оператор, записаний після слова then, і на цьому виконання закінчується. Але якщо це значення хибне, те виконується не перший, а другий оператор, записаний після else. Наприклад, при виконанні послідовності операторів
readln(x);
if x>=0 then z := 1 else z := -1
змінна z одержить значення 1, якщо прочитано невід'ємне значення x. Якщо ж прочитано значення від'ємне, то z одержить значення –1.
Оператор розгалуження в скороченій формі має вигляд:
if умова then оператор
Він відрізняється лише тим, що якщо обчислення умови дає значення false, то на цьому його виконання закінчується.
Як бачимо, оператори розгалуження містять умови, з обчислення яких і починається їх виконання. Тому ці оператори ще називаються умовними.
Застосуємо оператори розгалуження для перекладу алгоритму обчислення коренів на мову Паскаль. Пункт (3) можна, здавалося б, перекласти так:
if d>0 then x1:=(-b- sqrt(d))/(2*a); x2:=(-b+sqrt(d))/(2*a)
else
if d=0 then x1:=-b/(2*a);
{інакше нічого не робити}
Але це неправильно! Оператор розгалуження закінчується оператором присвоювання змінній x1. Оператор x2 := (-b+sqrt(d))/(2*a) записано уже за роздільником ";", тобто після оператора розгалуження. Те, що написано далі, взагалі не є оператором.
Як же записати послідовність із двох або більше операторів там, де має бути один? Напрошується відповідь, що їх треба взяти в дужки. І такі дужки, що перетворюють послідовність операторів у один оператор, у мові Паскаль є. Це так звані відкриваюча та закриваюча операторні дужки: ключові слова begin і end (початок і кінець).
Запис вигляду
begin послідовність операторів end
називається складеним оператором.
Отже, опишемо обчислення одного або двох коренів таким оператором розгалуження в повній формі:
if d>0 then
begin x1:=(-b+sqrt(d))/(2*a); x2:=(-b-sqrt(d))/(2*a) end
else
if d=0 then x1:=-b/(2*a)
Як бачимо, після слова then записано складений, а після слова else – оператор розгалуження в скороченій формі.
Оформимо алгоритм обчислення коренів у вигляді програми:
program roots(input, output);
var a, b, c: real; x1, x2: real;
begin
{1} readln(a,b,c); {припускаємо, що a<>0! }
{2} d:=b*b-4*a*c;
{3} if d>0 then
begin
x1:=(-b+sqrt(d))/(2*a);
x2:=(-b-sqrt(d))/(2*a)
end
else
if d=0 then x1:=-b/(2*a)
end.
Якщо при виконанні цієї програми задати значення змінних a, b, c, наприклад, відповідно 1, 3, 2, то справджується d>0, і обчислюються x1 і x2. Якщо задати значення 1, 2, 3, то умова d>0 хибна, обчислюється умова d=0, її значенням є false, і на цьому все закінчується. При значеннях 1, 2, 1 умова d=0 істинна, і обчислюється лише x1.
До програми слід додати оператори виведення, щоб вона не була занадто "мовчазною". Це залишається як вправа.
І останнє зауваження щодо структури операторів розгалуження. Розглянемо такий оператор:
if z>0 then if z>5 then k:=2 else k:=1
Хибності якої умови, z>0 чи z>5, відповідає else-гілка? Тобто чи є оператор
if z>5 then k:=2
оператором розгалуження в скороченій формі, чи він має повну форму
if z>5 then k:=2 else k:=1 ?
Відповідь на це питання дає наступне неформальне правило.
Будемо рухатися по тексту програми від слова else назад до найближчого слова if, пропускаючи при цьому складені оператори. Цьому слову if та хибності умови, записаної за ним, і відповідає else-гілка. Але якщо на шляху ми зустріли слово else, то за цим самим правилом спочатку відшукаємо відповідне йому if, і лише після цього продовжимо наши пошуки.
За цим