
Зубенко, Омельчук - Програмування. Поглиблений курс
.pdf
Розділ ІІ. ЕЛЕМЕНТИ ІНФОРМАТИКИ
си при цьому можуть перетинатися. Розглянемо основні класифікації мов програмування. Програми довільної мови програмування L до- мовимось називати L -програмами.
Як уже зазначалось у вступі, мови програмування розподіляються на практичні й теоретичні. Останні використовуються в теоретич- них моделях інформаційних систем та їхніх компонентів. Це стосуєть- ся в основному алгоритмічних мов.
Функціональна сила. Ця ознака притаманна теоретичним моделям мов, в яких немає обмежень на потужність типів даних і кількість даних у програмах, тобто потенційно ці величини вважаються зліченними. Якщо це тип цілих чисел, то він збігається з усіма цілими числами тощо. За даною ознакою мови програмування розподіляються на:
•універсальні;
•спеціалізовані.
Як випливає з принципу функціональності, будь-яка програма є функцією, що пов'язує вхідні дані з результатами, тобто кожній мові програмування L відповідає певна конкретна сукупність подібних функцій. Серед них можна виділити підмножину F базових елемен- тарних функцій, з яких за допомогою певних композицій будуються всі L -програми. У теорії алгоритмів існує поняття класу U(F) усіх ал- горитмічно обчислюваних функцій над даним базисом F . Якщо для кожної функції класу U(F) існує L -програма, що обчислює її відносно певних функцій кодування й декодування, то кажуть, що мова L є універсальною. У зворотному випадку мову називають спеціалізова- ною. Такі відомі мови програмування, як АЛГОЛ-60, ФОРТРАН, Lisp,
ПАСКАЛЬ, С, С++ , Java, PHP, Perl, Python та інші є універсальними25. Спеціалізованими є, наприклад, мови для підготовки програмної до- кументації (мова РПГ тощо).
Зауважимо, що універсальність мови програмування ще не означає її зручність для розв'язання тієї чи іншої конкретної задачі. Вона за- безпечує тільки теоретичну можливість такого розв'язання. Тому на практиці при виборі мови програмування враховують специфіку як задачі, так і конкретних мов та їхніх систем програмування (типів даних, стандартних бібліотек, операційного середовища тощо). Звідси випливає важливість нижченаведеної класифікації.
Предметна орієнтація. Зазвичай поштовхом для розробки й реа- лізації нової мови програмування або нової версії вже існуючої мови є бажання забезпечити ефективніше програмування запитів у певній
25 Перші мови програмування так і називали – універсальними, наприклад, Універса- льна мова програмування ПЛ/1.
191

ПРОГРАМУВАННЯ
предметній області, ніж це дозволяють існуючі мови та їхні системи програмування. Даний клас запитів визначає предметну орієнтацію мови. Предметна орієнтація мови знаходить своє відображення на- самперед у її типах даних, а також у структурах програм.
•Mови АЛГОЛ-60, ФОРТРАН-IV, АНАЛІТИК тощо орієнтовані на чи- слову обробку даних (задачі числового аналізу, лінійної алгебри, мате- матичної фізики й аналітичних перетворень та ін.). Для подібних за- дач характерними є порівняно прості структури даних (не виходять за межі багатовимірних масивів) і потужна ІЛП.
•Мови типу ПЛ-1, КОБОЛ, АЛГОЛ-68, ПАСКАЛЬ, С, С++, Delphi, Oberon, Java орієнтовані на обробку складноструктурованої інфор- мації. Вони мають розвинену систему типів даних зі структурами, покажчиками тощо й потужну ІЛП.
•Мови типу Modula, Аda – це мови, зорієнтовані на обробку даних
уреальному часі.
•Мови типу СНОБОЛ, Lisp, РЕФАЛ, ФОЛI зорієнтовані на символь- ну обробку, що є характерною для задач штучного інтелекту тощо.
•Мови типу Oracle, SQL зорієнтовані на розробку баз даних.
•Мови типу HTML, PHP, Perl зорієнтовані на задачі, пов'язані з
WEB-технологіями.
Рівень абстракції. За рівнем абстракції мови програмування роз- поділяють на:
•декларативні, або проблемно-орієнтовані;
•процедурно-орієнтовані.
Перші призначені для опису функціональної семантики програм, тобто того, що має робити програма, але не вказують як. У подібних мовах програма – це формальний опис результатів аналізу задачі. За- звичай цей опис задає функціональну семантику програми неявно за допомогою різних систем рівнянь, у тому числі й функціональних, за- писаних у тому чи іншому стилізованому фрагменті ПЧП. Прикладами подібних проблемно-орієнтованих мов є мови УТОПІСТ, НОРЕ, знач- ною мірою ПРОЛОГ тощо. Проблемно-орієнтовані мови використову- ють зазвичай на ранніх стадіях проектування для швидкого отриман- ня проміжних моделей, макетів і прототипів систем. При цьому праг- матичні вимоги можуть тимчасово залишатися на другому плані.
У процедурно-орієнтованих мовах програми специфікуються як функції-процедури. На сьогодні це основний інструментарій у існую- чих технологіях програмування. Вони поділяються на два класи:
• мови високого рівня призначені для формування запитів: мови типу АЛГОЛ-60, ПАСКАЛЬ, С, С++ тощо;
192

Розділ ІІ. ЕЛЕМЕНТИ ІНФОРМАТИКИ
•машинно-залежні мови – це внутрішні алгоритмічні мови ЕОМ або наближені до них: мова НМ, асамблерні й макроасамблерні мови, автокоди, бінарні коди програм.
Мови високого рівня характеризуються зручним для людини син- таксисом, структури даних і програм мають абстрактну математичну семантику, інваріантну відносно архітектури конкретних ЕОМ. Ма- шинно-залежні значною мірою зберігають структуру конкретних ма- шинних мов. Проміжну позицію між мовами високого рівня й ма- шинно-залежними займають високорівневі внутрішні мови, напри- клад Адресна, ФОЛІ тощо.
Парадигми. Мови програмування можуть класифікуватися за пара- дигмами програмування, які вони підтримують (повною мірою або част- ково). Мова може підтримувати кілька парадигм. Кожна з парадигм орі- єнтується на певні моделі програм і даних, відповідні засоби їхнього опи- су й методи реалізації. Найвідомішими парадигмами програмування є:
•Декларативне програмування. Має справу з програмами у ви-
гляді формального опису співвідношень між вхідними й вихідними даними задачі. Зазвичай цей опис задає функціональну семантику програми неявно за допомогою різних систем рівнянь.
•Процедурне програмування. Має справу з програмами, що міс- тять процедури розв'язання задач. Підтримується більшістю мов про- грамування.
•Функціональне програмування. Програми специфікуються у ви-
гляді функцій-процедур із широким застосуванням індуктивних ви-
значень. Мови Lisp, РЕФАЛ, ML, Haskell, Pyhton.
•Програмування з абстрактними типами даних (АТД). Для спе-
цифікації програм використовуються АТД з об'єктами, класами та ін-
капсуляцією. Мови SІMULA-67, Modula, Аda, С++.
•Логічне програмування. Програми специфікуються у вигляді спе- ціальних формул ПЧП. Найбільшого поширення набула мова Prolog.
•Об'єктно-орієнтоване програмування (ООП). ООП – це методоло-
гія програмування, що базується на зображенні програми у вигляді сукупності об'єктів, кожен з яких є екземпляром певного класу, а класи утворюють ієрархію спадкування. Ураховуючи значну популя- рність цієї парадигми, зупинимось на ній детальніше.
Об'єктно-орієнтовані можливості класів забезпечують три найваж- ливіші властивості ООП:
1) Інкапсуляція – це механізм, який об'єднує дані й методи, що ма- ніпулюють даними, у класи й захищає їх від зовнішнього впливу чи неправильного використання.
193

ПРОГРАМУВАННЯ
2)Спадкування – можливість породжувати один клас на основі ін- шого зі збереженням усіх атрибутів і методів батьківського класу й додавати за необхідності нові атрибути й методи. Набір класів, пов'я- заних відношенням спадкування, називають ієрархією.
3)Поліморфізм – явище, при якому один і той самий програмний код виконується по-різному, залежно від того, об'єкт якого класу використо- вується при виклику даного коду. Поліморфізм забезпечується тим, що в класі-нащадку змінюють реалізацію методу батьківського класу з обов'я- зковим збереженням сигнатури методу. Це забезпечує збереження не- змінним інтерфейсу батьківського класу й дозволяє здійснювати дина- мічне зв'язування імені методу в коді з різними класами – з об'єкта яко- го класу здійснюється виклик, з того самого класу й береться метод із заданим іменем. Мови об'єктного програмування поділяються на об'єк- тні, в яких існують класи й об'єкти (SIMULA-67), і об'єктно-орієнтовані,
вяких програміст може не лише користуватися визначеними класами, але й задавати свої. Відомими об'єктно-орієнтованими мовами є
Smalltalk, Oberon, С++, С#, Java, JavaScript тощо.
•Паралельне програмування. Для специфікації програм викорис- товуються засоби розпаралелювання процесів. Мови Ada, Java, HighPerformance FORTRAN.
•Агентне програмування. У центрі уваги – агент, самодостатня програма, здатна керувати своїми діями в розподіленому інформа- ційному середовищі, структура якого може динамічно змінюватися. Підтримують мови Java, частково – Zonnon.
Типізація. Розрізняють мови зі статичною (сильною) і динамічною
(слабкою) типізаціями. У першому випадку змінні й параметри функ- цій (методів) зв'язуються з типами в момент опису або декларування
йне можуть бути змінені пізніше. Це, окрім спрощення трансляції й керування пам'яттю, дає можливість здійснювати часткову перевірку семантичної коректності використання змінних уже на етапі компі- ляції, зокрема перевірку узгодженості їхніх типів із типом операцій. У другому випадку змінні й параметри функцій (методів) зв'язуються з типами в момент присвоювання значення або передавання парамет- ра у функцію. У цьому випадку одна й та сама змінна в різні моменти виконання програми може буде зв'язана зі значеннями різних типів.
•Статична типізація. Мови ФОРТРАН, АЛГОЛ-60, ПАСКАЛЬ, С,
С++, Modula.
•Динамічна типізація. Мови Lisp, ML, Pyhton, Perl, Smalltalk.
Наведені класифікації мов програмування склалися історично й ві-
дображають переважно прагматичні властивості мов і особливості їх-
194

Розділ ІІ. ЕЛЕМЕНТИ ІНФОРМАТИКИ
ньої трансляції. Сьогодні існує проблема створення наукового підходу до класифікації й порівняльного аналізу мов програмування за тими чи іншими ознаками їхньої внутрішньої структури. Виходячи з прого- лошених нами загальних і спеціальних принципів програмування, мо- жна стверджувати, що будь-який науковий підхід до класифікації мов програмування має спиратись на попереднє уточнення вежі типів да- них, яка визначає всю логіко-функціональну семантику мови. Легкість моделювання базової Ω -системи типів мови, а також конструкторів для побудови похідних типів засобами іншої мови, характеризує поді- бність двох мов або реальну логіко-функціональну різницю між ними.
*Література для CР: знакові системи – [56, 63, 81]; мови програмування – [103, 114]; класифiкацiя мов програмування – [114]; парадигми й стилі програмування – [10, 52, 90, 91]; інтелект-карти – [117].
Контрольні запитання та вправи
1.Що таке ДС?
2.Що таке синтаксис, семантика та прагматика ДС?
3.Що таке знак-символ?
4.Що таке ідеограма? Навести приклади.
5.Що так денотат?
6.Що таке термін?
7.Що таке трикутник віднесення?
8.Які бувають терміни?
9.Що таке дескрипція? 10. Що таке метамова?
11. Що таке кодова таблиця?
12. Які коди відповідають символам кирилиці (укр.) у кодових таблицях: а) ASCII; б) Unicode); в) UCS-2; г) UCS-4?
13. Що таке широка літера?
14. Що таке лексема й лексика мови?
15. Що таке денотаційна й операційна семантики програми?
16. Що таке операційний об'єкт?
17. Що таке зв'язування змінної?
18. Що таке дескриптор змінної?
19. Яка роль операторів-описів і операторів-декларацій? 20. Що таке вираз мови програмування?
21. Що таке первинний оператор?
22. У чому полягає прагматика програми?
23. Який програміський сенс трикутників віднесення?
195

ПРОГРАМУВАННЯ
24.Які основні аспекти програм?
25.Що таке вежа типів мов програмування?
26.Що таке об'єднана Ω -система типів мови програмування?
27.Охарактеризувати основні класифікації мов програмування.
28.У чому полягає класифікація мов програмування за предметною орієнтацією?
29.У чому полягає класифікація мов програмування за рівнем абстракції?
30.Що таке мови високого рівня й машинно-залежні?
31. Сформулювати |
ознаки |
парадигм: а) декларативного; |
б) процедурного; |
в) |
функціонального; г) логічного; |
д) об'єктно-орієнтованого; е) паралельного; є) агентного програмування.
32.Яка різниця між статичною й динамічною типізаціями?
2.5.Структурні програми й рекурентні функції
¾Структурні схеми програм і структурні алгоритми
¾Системи рекурентних послідовностей
¾Рекурентні функції
¾Техніка побудови стандартних програм
структурна схема програм, інтерпретація ССП, структурний алгоритм, абстрактна структурна програма, система рекурентних послідовностей, конструктор рекурентної послідовності, система m-рекурентних послідовностей, вхідна, опорна й проміжна послідовності, вимір системи рекурентних
послідовностей, μ -оператор, рекурентна й m-рекурентна функція, параметризована рекурентна функція.
Означені у підрозд. 2.1.5 структурні алгоритми становлять основу циклічних конструкцій процедурних мов програмування. Необхідно лише доповнити їх інтерфейсними функціями й відповідними опера- ціями присвоювання для роботи з іменованими даними. У даному підрозділі розглядається універсальний метод побудови таких алгори- тмів і програм. Він спирається на поняття системи рекурентних по- слідовностей і рекурентної функції.
Однак спочатку розглянемо лінійну форму структурних алгоритмів.
196

Розділ ІІ. ЕЛЕМЕНТИ ІНФОРМАТИКИ
2.5.1. СТРУКТУРНІ СХЕМИ ПРОГРАМ І СТРУКТУРНІ АЛГОРИТМИ
Структурні схеми програм (ССП) є словесними формами структур- них блок-схем. Вони теж визначаються алгебрично як елементи зами- кання, породженого базовими схемами Box , Сon1 , Сon2 за допомогою
ключових слів while, do, case, detcase, if, else і допоміжних символів {, }, (, ), :. Схеми Сon1 та Сon2 подають довільний і заключний предикати26.
Нехай P1,...,Pn – довільні ССП. Нові ССП будуються таким чином:
1)складена CСП: {P1...Pn };
2)розгалуження: if (Con1) P1 else P2 ;
3)обхід: if (Con1)P ;
4)недетермінований вибір: case {Con1: P1,...,Con1: Pn };
5)детермінований вибір: detcase {Con : P1,...,Con : Pn }, де Сon – це
Сon1 або Сon2 ;
6)ітерація: while (Сon1)P;
7)повторення: do P while (Сon1).
Отже, ССП є або базовими, або мають вигляд 1)–7). Фактично ССП є термами регулярної алгоритмічної алгебри, записаними в стилі, набли- женому до мов програмування (див. підрозд. 1.4.3). При цьому в ССП, на відміну від регулярних термів, логічні вирази не структуровані.
Інтерпретуються ССП так само, як і структурні блок-схеми. Вхо- дження елементів Box та Con1, Con2 замінюються елементарними пе- ретвореннями станів і предикатами певного обчислювального прос-
тору Π = < Γ,S, |
>. |
|
|
|
|
|
|
|
|
||
Інтерпретацією |
ССП |
|
P |
називається |
трійка |
I = (S, |
,δ), де S – |
||||
множина станів, |
= {ϕ1,...,ϕk } {γ1,...,γl } |
– сукупність елементарних |
|||||||||
перетворень |
станів |
і |
предикатів |
на |
станах, |
ϕi : S → S , |
|||||
i = |
1,k |
, γj : S → Bool , |
j = |
1,l |
, δ |
– функція, яка кожному входженню ба- |
зового елемента схеми ставить у відповідність певний елемент з ін- терпретації схеми – елементарне перетворення, якщо базовим елеме- нтом є Box; елементарний предикат, якщо ним є Сon1 або Сon2 . Предикати, що відповідають входженням Сon2 , вважаються заключ- ними. Інтерпретовані ССП, як і інтерпретовані СБС, називаються
структурними алгоритмами й позначаються P I .
26 Заключні предикати використовуються в детермінованому виборі (див. підрозд. 1.3.3).
197

ПРОГРАМУВАННЯ
Опишемо семантику структурних алгоритмів. Вона визначається структурою схем їхніх програм і відповідає семантиці регулярних композицій функцій. Нехай P0,P1,...,Pn – довільні CСП; I = (S, ,δ) –
деяка їхня спільна інтерпретація; ϕi : S → S |
– функція, що є значен- |
||||||
ням ССП P |
при інтерпретації I , тобто P I |
= ϕ ,i = |
|
; Con ,...,Con |
|
та |
|
1,n |
n |
||||||
i |
i |
|
i |
1 |
|
Con11,...,Con1n – послідовності базових схем Сon1 та Сon2 і відповід- но схеми Сon1; ρi ,θi ,i =1,n – елементарні предикати – значення Coni та Con1i при інтерпретації I .
Для P = Box покладемо P I = BoxI .
Увага! Щоб зробити ССП і алгоритми зрозумілішими, будемо вста- вляти в їхній текст коментарі-пояснення вигляду /*…*/, які не впли- вають на дію програм і можуть бути без наслідків вилучені з них ►
Для P = {P ...P } |
P I |
= ϕ ...ϕ |
|
. /*Множення*/ |
|
|
|
|
||||||
1 |
n |
|
1 |
n |
|
|
|
|
|
|
|
|
|
|
Для P = if(Con1 )P elseP |
P I |
= (θ → ϕ |ϕ ). /*Розгалуження*/ |
|
|||||||||||
|
1 |
1 |
|
2 |
|
|
|
1 |
1 |
2 |
|
|
|
|
Для P = if (Con1)P |
P I = (θ → ϕ ). /*Обхід*/ |
|
|
|
|
|||||||||
|
|
1 |
|
1 |
|
1 |
|
|
|
|
|
|
||
Для P = case{Con1 |
: P ;...;Con1 : P } |
P I |
= (θ → ϕ || … || θ |
→ ϕ |
). |
|||||||||
|
|
1 |
1 |
|
|
|
n |
n |
|
1 |
1 |
n |
n |
|
/*Вибір*/ |
|
|
|
|
|
|
|
|
P I = (ρ1 → ϕ1 | … | ρn → ϕn ). |
|
||||
Для P = detcase{Con1 : P1;...;Conn : Pn } |
|
|||||||||||||
/*Детермінований вибір*/ |
|
|
|
|
|
|
|
|
|
|||||
Для P = while(Con11 )P1 |
P I |
={θ1 → ϕ1}. /*Ітерація*/ |
|
|
|
|||||||||
Для P = doP |
while(Con1 ) |
|
P I = |
θ → ϕ |
. /*Повторення*/ |
|
|
|
||||||
1 |
|
|
|
1 |
|
|
|
1 |
1 |
|
|
|
|
|
Повернемося до структурних алгоритмів із прикл. 2.4.
Приклад 2.21. Структурні алгоритми для обчислення функцій
sign(x ), ± x |
і найбільшого спільного дільника двох чисел: |
|
case{x < 0 : −1;x = 0 : 0;x > 0 :1} /*обчислює функцію sign(x )*/; |
||
case{x ≥ 0 : |
x ;x ≥ 0 : − x } |
/*обчислює ± x */; |
{ while(q ) do if (p)α else β |
pr1 } /*обчислює НСД ( x,y ), де елемента- |
рні операції та предикати ті самі, що й у прикл. 1.8*/■
Важливу роль відіграють абстрактні структурні програми. Це структурні алгоритми зі спеціально структурованими станами й опе- раторами присвоювання в якості елементарних перетворень станів. Праві частини цих операторів задаються термами певної алгебричної
198

Розділ ІІ. ЕЛЕМЕНТИ ІНФОРМАТИКИ
системи A = (U ;ΩF ;ΩP ) (будемо називати її базовою), а ліві є іменами, що належать деякій сукупності імен V = {x,x1,...y,y1,...}. При цьому
терми (у тому числі й предикатні) трактуються як еквітонні X -арні операції, імена змінних у яких розглядаються як операції читання (див. прикл. 2.2). Предикатні терми називаються умовами. Стани та- ких програм – це інформаційні поля об'єктів з іменами з V і значен- нями з універсума U. Абстрактні програми можуть мати параметри – фрейми X та Y , що визначають відповідно вхідні й вихідні змінні. Графіками таких програм є певні X −Y -оператори O . Кажуть, що аб-
страктна програма обчислює векторний аналог O свого X −Y - оператора. Якщо абстрактна програма не містить схем детермінова- ного вибору, то її називають стандартною. Базова алгебрична систе- ма A може бути багатосортною Ω -системою.
Абстрактні структурні програми над багатосортними базовими Ω -системами є формальними моделями програм мов програмування
із простими структурами даних.
Як приклад стандартної програми розглянемо ще один варіант ал- горитму Евкліда для обчислення НC Д(n,m ).
Приклад 2.22. Обчислення НCД(n,m) через залишки від ділення чисел:
/*Вх: |
x,y |
Вих: x*/ |
while |
(x ≠ y) do if (x<y) |
y ←y%x; else x ←x%y; |
Параметризований векторний аналог даної програми зі вхідними змінними x,y і вихідною x збігається з НОД(n,m). Станами програ-
ми є інформаційні поля з двома змінними: {(x,n ),(y,m )}, де n,m N ,
які змінюються в процесі обчислення операторами присвоювання y ←y%x; та x ←x%y;. У результуючому стані значення змінних однако-
ві й дорівнюють НОД(n,m)■
2.5.2. СИСТЕМИ РЕКУРЕНТНИХ ПОСЛІДОВНОСТЕЙ
Нехай T – довільний універсум елементів, f ,g,... – певні часткові
операції на T , які будемо називати конструкторами рекурентних послідовностей. Система послідовностей
199

ПРОГРАМУВАННЯ
a0,a1,... Tb0,b1,... T...
називається рекурентною відносно конструкторів f ,g,..., якщо всі її члени, за винятком, можливо, перших, пов'язані співвідношеннями
(*)ai = f (ai −1,bi −1,...), bi = g (ai −1,bi −1,...), ..., i =1,2,....
Кількість послідовностей у системі називається її виміром, а самі послідовності – рекурентними. Ми розглядатимемо тільки рекурентні системи певного фіксованого скінченного виміру. Щоб повністю ви- значити таку систему, достатньо задати нульові члени a0,b0,... і конс-
труктори. Решту членів знаходять за допомогою конструкторів. Дійс-
но, a1 = f (a0,b0,...), b1 = g (a0,b0,...) тощо.
Іноді зручно нумерувати члени рекурентних послідовностей, розпо- чинаючи з 1. Члени рекурентних послідовностей можуть залежати від членів не всіх сусідніх послідовностей, а тільки деяких, тому на прак- тиці конструктори можуть мати (і зазвичай мають!) різну арність. У деяких випадках у системі співвідношень (*) наступні члени послі- довностей можуть обчислюватись не тільки за попередніми, а й за по- точними членами сусідніх послідовностей, а також за своїм індексом. В останньому випадку це означає, що в системі неявно присутній лі- чильник (див. прикл. 2.23).
Розглянемо кілька відомих прикладів рекурентних послідовностей. Приклад 2.23. Рекурентні послідовності:
1) Послідовність-константа: (*)a1 = a2 = ... = c .
Конструктор – тотожна операція f (x) = x.
2)Арифметична прогресія з різницею d:
(*)a1 = a, a1 = ai −1 + d , i >1.
Конструктор – операція f (x) = x + d .
3)Лічильник i : арифметична прогресія з початковим членом 0 або
1і різницею d =1. Значення лічильника на к-му кроці збігається з к.
4)Геометрична прогресія зі знаменником q :
(*) b1 = b, bi = bi −1 ×q , i >1.
Конструктор – операція f (x) = x ×q . 5) Гармонічні числа:
200