Text
                    /. О. Хвищун
Академічний
Підручник



Міністерство освіти і науки України Львівський національний університет імені Івана Франка І. Оі Хвищун ПРОГРАМУВАННЯ і МАТЕМАТИЧНЕ МОДЕЛЮВАННЯ Підручник Затверджено Міністерством освіти і науки України як підручник для студентів вищих навчальних закладів Видавничий центр ЛНУ імені Івана Франка Київ 2007
УДК [004.43+519.6+519.622] (075.8) ББК 3973.2-018я73+В19я73 ХЗО Рецензенти: B. А. Кривень, д-р фіз.-мат. наук, проф. (Тернопільський державний технічний університет імені Івана Пулюя); Р. А. Мельник, д-р техн. наук, проф. (Національний університет “Львівська політехніка”); C. А. Федосов, д-р фіз.-мат. наук, проф. (Луцький державний технічний університет) Гриф надано Міністерством освіти і науки України (Лист № 14/18.2-689 від 17.03.06 р.) Хвищун І. О. ХЗО Програмування і математичне моделювання: Підруч. - К: Видавничий Дім “Ін Юре”, 2007. — 544 с.: іл. ISBN 978-966-613-516-5 ІБВК 978-966-313-315-5 У підручнику викладено основи програмування мовою Вогіагиі Ра5саІ. Наведено чисельні методи, алгоритми і приклади програм для розв’язання фізичних та науково-технічних задач, зокрема — методи розв’язання нелінійних рівнянь, методи розв’язання систем лінійних, нелінійних та диференціальних рівнянь, методи чисельного диференціювання та інтегрування, методи обробки експериментальних результатів та їхньої графічної візуалізації, а також математичного моделювання динамічних режимів фізичних систем. Для студентів вищих навчальних закладів, які навчаються за напрямами -“Фізика”, “Комп’ютеризовані системи, автоматика та управління”, а також студентів природничих і технічних коледжів. УДК [004.43+519.6+519.622] (075.8) ББК 3973.2-018я73+В19я73 © Хвищун І. О., 2007 © Львівський національний університет 15ВЫ 978-966-613-516-5 імені Івана Франка, 2007 15ВЫ 978-966-313-315-5 © Видавничий Дім “Ін Юре”, 2007
Зміст ПЕРЕДМОВА 9 ВСТУП 17 1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 19 1.1. Сутність програмування 19 1.2. Мови програмування. Коротка історія 23 1.3. Компілятори, інтерпретатори, лінкери, завантажувачі 27 1.4. Поняття інформації. Властивості інформації..... 29 1.5. Інформатика ЗО 1.6. Поняття алгоритму. Властивості алгоритмів 33 1.7. Форми представлення алгоритму 34 1.8. Порівняння форм запису алгоритму 39 1.9. Приклад розв’язання квадратного рівняння 39 1.10. Етапи розробки програмного забезпечення 43 1.11. Вимоги до програмування 47 1.12. Стиль програмування 50 2. МОВА BORLAND PASCAL 55 2.1. Переваги мови Pascal 55 2.2. Поняття інтегрованого середовища 58 2.3. Робота в інтегрованому середовищі Borland Pascal 60 2.3.1. Початок і завершення роботи 61 2.3.2. Вікна системи 62 2.3.3. Допомога (HELP) 66 2.3.4. Команди екранного редактора 67 2.3.5. Система меню середовищаВР 70 2.4. Елементи мови Borland Pascal 86 2.4.1. Алфавіт мови 86 2.4.2. Ключові слова 87 2.4.3. Елементарні конструкції 88 2.4.4. Поняття типу для даних 90 2.4.5. Скалярні типи даних 92 2.4.6. Константи 98 2.4.7. Вирази 98 2.4.8. Бітова арифметика 99 2.5. Оператори введення і виведення 100 2.5.1. Апаратне забезпечення 100 2.5.2. Введення/виведення текстової інформації 101 2.5.3. Робота з псевдографікою 103
4 2,5.4. Графічні засоби середовищаВР 107 2.6. Структура програми 112 2.7. Підпрограми 115 2.7.1. Процедури 116 2.7.2. Програма табулювання функції 118 2.7.3. Локальні і глобальні змінні 120 2.7.4. Процедури з параметрами 122 2.7.5. Функції 124 2.8. Стандартні підпрограми 126 2.9. Рекурсія 129 2.9.1. Приклади програм з рекурсією 131 2.10. Керуючі структури програми 135 2.10.1. Оператор присвоювання := 135 2.10.2. Оператор безумовного переходу GOTO 135 2.10.3. Умовні оператори (розгалуження) 136 2.10.4. Цикли 140 2.11. Розв’язання нелінійних рівнянь 149 2.11.1. Метод половинного ділення 151 2.11.2. Особливі випадки МПД 152 2.11.3. Алгоритм МПД 154 2.11.4. Програма МПД 155 2.11.5. Метод Ньютона для розв’язання нелінійних рівнянь 156 2.11.6. Алгоритм методу Ньютона 159 2.12. Обчислення визначених інтегралів 161 2.12.1. Площа криволінійної фігури 161 2.12.2. Визначений інтеграл 162 2.12.3. Методи чисельного інтегрування 164 2.12.4. Методи прямокутників 166 2.12.5. Апостеорні оцінки похибок за Рунге та Ейткеном 169 2.12.6. Метод трапецій 171 2.12.7. Метод парабол (Сімпсона) 172 2.12.8. Програмування методів обчислення визначених інтегралів. 174 2.12.9. Обчислення інтегралів із заданою точністю 175 2.12.10. Програма обчислення інтегралів із заданою точністю 176 2.12.11. Метод Монте-Карло 177 2.12.12. Програма методу Монте-Карло 180 2.13. Масиви (Array) 181 2.13.1. Опис масивів 183 2.13.2. Заповнення елементів масиву значеннями 185 2.13.3. Програма введення/виведення елементів матриці 187 2.14. Налагодження програм засобами середовища ВР 188 2.14.1. Генерування налагоджувальної інформації 191 2.14.2. Виконання програми по кроках 193
5 2.14.3. Налагодження із зупинками 195 2.14.4. Відстеження і модифікація 197 2.14.5. Трасування складних програм 200 3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 205 3.1. Системи лінійних рівнянь 205 3.1.1. Рівняння з одним невідомим 208 3.1.2. Системи двох лінійних рівнянь з двома невідомими 208 3.1.3. Формулювання узагальненої задачі 209 3.1.4. Зведення матриці системи до трикутного вигляду 210 3.1.5. Обчислення визначника матриці 211 3.1.6. Метод Крамера 215 3.2. Метод Гауса розв’язування систем лінійних рівнянь 217 3.2.1. Обчислювальна схема 217 3.2.2. Алгоритм методу Гауса 219 3.2.3. Головна програма для розв’язання CJIAP 221 3.2.4. Процедура методу Гауса 222 3.2.5. Тестова задача 223 3.3. Метод L{/-перетворення 224 3.3.1. Алгоритм LCT-перетворення 225 3.3.2. Процедура Decomp 227 3.3.3. Процедура So/ve 228 3.3.4. Обумовленість матриць 230 3.4. Розв’язування систем нелінійних рівнянь 232 3.4.1. Метод простої ітерації 232 3.4.2. Метод Ньютона 233 3.4.3. Алгоритм методу Ньютона 235 3.4.4. Блок-схема алгоритму Ньютона 237 3.4.5. Реалізація алгоритму методу Ньютона 238 3.5. Модулі (Unit) 240 3.5.1. Структура модуля 241 3.5.2. Інтерфейсна секція (Interface) 241 3.5.3. Секція реалізації (Implementation) 242 3.5.4. Секція ініціалізації 243 3.5.5. Використання модулів 243 3.5.6. Створення власних модулів 244 4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 247 4.1. Графічне середовище ВР 247 4.1.1. Установлення роздільної здатності екрана 247 4.1.2. Очищення графічного екрана 248 4.1.3. Установлення кольорів 248 4.1.4. Виведення піксела на екран 249
6 4.1.5. Виведення ліній на екран 249 4.1.6. Переміщення графічного курсора 249 4.1.7. Виведення ламаних і багатокутників 250 4.1.8. Виведення дуги, кола, еліпса 250 4.1.9. Вибір типу лінії для малювання 251 4.1.10. Вибір структури заповнювача ділянок екрана 252 4.1.11. Програма показу шаблонів зафарбовування 253 4.1.12. Заливання замкнутої області 254 4.1.13. Виведення на екран заповнених фігур 255 4.1.14. Виведення тексту на екран 255 4.1.15. Програма виведення діаграми та гістограми 257 4.1.16. Програма, яка виводить шахову дошку 258 4.2. Побудова графіків функцій 259 4.2.1. Математичний аспект 259 4.2.2. Аспект програмування 262 4.2.3. Програма побудови графіків функцій 263 4.3. Програмування рухомих зображень 266 4.3.1. Вказівники і динамічна пам’ять 266 4.3.2. Алгоритм переміщення зображення графічним екраном 267 4.3.3. Програма, що виконує рух кульки екраном 269 4.4. Керування рухом зображення графічним екраном 270 4.4.1. Алгоритм керування рухом зображення 270 4.4.2. Програма керування рухом зображення 271 4.5. Записи {Record) 272 4.5.1: Оператор приєднання' With 274 4.5.2. Записи з варіантами 277 4.5.3. Використання записів у графіці 279 4.5.4. Програма. Рух “ракети” зліва направо 281 4.5.5. Використання записів при виведенні дуг 282 4.5.6. Програма “пульсуюче серце” 284 4.6. Обертання двовимірних зображень 285 4.6.1. Програма обертання “ракети” 287 4.7. Фракталй 289 4.7.1. Класифікація фракталів 292 4.7.2. Алгоритм побудови фрактала Мандельброта 296 4.7.3. Програма побудови фрактала Мандельброта 300 4.7.4. Програма побудови трикутника Серпінського 301 4.8. Файли : 302 4.8.1. Фізична будова та логічна організація вінчестера 303 4.8.2. Системні сектори 305 4.8.3. Класифікація файлів 307 4.8.4. Файли і каталоги 307 4.8.5. Параметри файлів 308
7 4.8.6. Особливості FAT16 308 4.8.7. Особливості FAT32 310 4.8.8. Файли у Pascal-ирогршах 312 4.8.9. Процедури та функції загального призначення 316 4.8.10. Робота з файлами різних типів 320 5. ЗВ’ЯЗОК PASCAL-AСЕМБЛЕР. 331 5.1. Що таке Асемблері 333 5.2. Асемблер і Макроасемблер 336 5.3. Техніка програмування 337 5.4. Коли Асемблер без альтернативи? 338 5.5. Робота в Асемблері 341 5.6. Формат команд Асемблера 342 5.7. Логічні основи роботи 7/і*е/-сумісних МП 343 5.7.1. Регістри МП 343 5.7.2. Типи даних 351 5.7.3. Опис та ініціювання даних 355 5.8. Робота з оперативною пам’яттю 359 5.8.1. Моделі пам’яті 360 5.8.2. Адресування даних у пам’яті 361 5.9. Система команд 364 5.9.1. Команди переміщення даних 364 5.9.2. Арифметичні команди 367 5.9.3. Побітові команди 369 5.9.4. Команди передачі управління 370 5.9.5. Рядкові команди 374 5.9.6. Система переривань 376 5.9.7. Команди управління 381 5.10. Математичний копроцесор 383 5.10.1. Типи даних 383 5.10.2. Регістри копроцесора 385 5.10.3. Команди копроцесора 385 5.11. Вставка в Pascal-npoграму фрагментів на Асемблері 390 6. ОБ’ЄКТНО-ОРІЄНТОВАНИЙ ПІДХІД У ПРОГРАМУВАННІ.... 393 6.1. Технології програмування 393 6.2. Суть об’єктно-оріентованого програмування 397 6.3. ООП і Borland Pascal 399 6.4. Головні характеристики ООП 400 6.5. Проектування (створення) об’єктів у ВР 404 6.6. Програма, що демонструє принципи ООП 410 7. МЕТОДИ Й АЛГОРИТМИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 413
8 7.1. Розробка головної програми 413 7.2. Спектральний аналіз періодичних сигналів 422 7.3. Інтерполювання 429 7.4. Дослідження інтерполяційного полінома Лагранжа 431 7.5. Локальне інтерполювання за методикою Ейткена 435 7.6. Дослідження інтерполяційного полінома Ньютона 440 7.7. Інтерполювання сплайнами 446 7.8. Метод прогонки 454 7.9. Апроксимування методом найменших квадратів 459 8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 465 8.1. Загальні принципи моделювання 465 8.1.1. Типи моделей 466 8.1.2. Особливості ММ фізичних систем 470 8.1.3. Дискретизація рівнянь ММ 473 8.2. Явний метод Ейлера 476 8.3. Методи Рунге-Кутта 479 8.3.1. Оцінка похибки на основі формул різної точності 480 8.3.2. Комбінація незалежних формул 480 8.3.3. Комбінація спеціальних формул 481 8.3.4. Контрольні члени методів Рунге-Кутта 482 8.3.5. Модифікація Мерсона 483 8.3.6. Модифікація Фельберга 484 8.4. Жорсткі системи диференціальних рівнянь 485 8.5. Неявний метод Ейлера 487 8.5.1. Алгоритм вибору початкового кроку інтегрування 489 8.5.2. Алгоритм вибору поточного кроку інтегрування 489 8.5.3. Позначення блок-схем НМЕ 491 8.5.4. Блок-схеми алгоритмів 493 8.5.5. Програма для розв’язання систем ЗДР 498 8.6. Тестові задачі 504 8.7. Багатокрркові методи 510 8.7.1. Метод Шичмена 511 8.8. Алгоритми автоматичного вибору величини кроку к 512 9. МОМЕНТИ ІСТОРІЇ ОБЧИСЛЮВАЛЬНОЇ ТЕХНІКИ 515 9.1. Ера механічних обчислювальних пристроїв 515 9.2. Ера електронно-обчислювальних пристроїв 520 ЛІТЕРАТУРА 525 АЛФАВІТНИЙ ПОКАЖЧИК 532
ПЕРЕДМОВА Програмування - це цікаво. Чому? Важко відповісти на таке запитання дотепніше та емоційніше, ніж це зробив у своїй статті Євген Скляревський [88]. Автор зазначив: "...комп’ютер перестав бути засобом написання програм, а став вікном в Інтернет, живою енциклопедією, альбомом фотографій, друкарською машинкою і великим тетрісом. Шкода - не тому, що став, а тому, що перестав. ...писати програми дуже приємно. Робота на персональному комп’ютері (ПК) збуджує позитивні емоції. Психологи помітили такий ефект: людині приємно навіть просто натискати на клавіші, не кажучи вже про маніпулювання мишею з яскравими кнопками. Передусім приваблива робота на ПК в сучасних графічних середовищах - на фоні улюбленої, заставки. Гарні іконки, вікна, звуки, курсори: - усе це можна налаштовувати на свій смак і змінювати щомісяця, або кожні 10 хвилин. Повертаюся до головної думки: приємний власне сам процес написання (обдумування, кодування та налагоджування) програм. Навіть якщо це нудний облік руху майна чи тестик з двох команд. У будь-якому випадку - це, передусім, спілкування з комп’ютером, з мовою програмування - з розумним, дотепним, уїдливим, вредним і водночас доброзичливим співрозмовником, який, на відміну від людей, не підвладний поганому настрою, поганому характеру і поганому вихованню. Це не просто спілкування, а спільна взаємозалежна діяльність зі створення добре працюючої програми. Навіть більше - це справжнє, захоплююче, повноцінне життя, а все, що поза ним - блякле і нецікаве очікування старості. Все вищесказане звелося до заклику: “Хлопці, пишіть програмиГ Знайдіть і встановіть який-небудь Вазіс або ТигЬо
10 ПЕРЕДМОВА Разсаі (версії 5.0, 5.5 або, скажімо, 7.0, що входить в пакет ВогІапЛ Разсаі 7.0). Спробуйте вивести на екран повідомлення, потім виведіть його в різних зонах екрана, потім змініть колір і фон літер. Намалюйте лінію, коло, прямокутник, змініть їхні параметри. Виконуючи ці досліди, Ви потрапите під магічну дію особливої внутрішньої пружини: “А що, якщо щось змінити?” І спробуйте, змініть. Ваші досліди - це найкраще застосування для Вашого комп’ютера. Навіть найпростіші, вони збільшують суму знань всього людства, якщо це для Вас важливо. Якщо ні - все одно: демонструючи отримані цікаві результати, Ви залучите до програмування хоча б одного із сотні знайомих, а той, можливо, ще когось. Це так само достойно, як і посадити дерево. Ті, кого хвилює практичне застосування, обов’язково знайдуть, що можна доручити комп’ютеру зі своїх клопотів - особистих, на роботі, удома - скрізь. А ті, кому важливіше отримати відповіді на цікаві запитання (наприклад, кількість щасливих квитків або рівняння квітки бузку), отримають перепустку в казкову країну прекрасної, хоча й не завжди потрібної, інформації. ...навіщо нам потрібен співрозмовник? Кожній людині необхідно щось розказувати. Коли ми говоримо, відбувається процес розкладання “на полички” нових думок, які ще не знайшли свого місця, звільнення “місдя” для їхньої наступної порції. Якщо людина довго не розповідає, вона відчуває дискомфорт, що може перейти у невроз. Зверніть увагу: під час бесіди кожний поспішає виговоритися, не слухаючи співрозмовника (до речі, написання листів і статей - це те ж саме “виговорювання”, потрібне тільки автору: не треба нічого читати, окрім моїх статей). Так от: комп’ютер володіє психотерапевтичним ефектом, замінюючи, в певному наближенні, співрозмовника. Будь-які маніпуляції з комп’ютером - навіть набір тексту та укладання кольорових кульок, можливо, рятують нас від шизофренії. Світ безповоротно розділився на тих, котрі всю ніч малюватимуть фрактали, крутитимуть флексагони та підбиратимуть стійкі конфігурації у грі “Життя”, і тих, котрі стримуючи позіхання, скажуть: “Гарно, тільки навіщо це потрібно?” Не відповідатимемо. Якщо людина запитує, значить, їй вже не* можна пояснити, хай доживає решту свого життя сіро і непоказно. За словами Лазарєва, автора “Діагностики Карми” (одна з найгучніших теорій серед тих, що виникли після відміни
ПЕРЕДМОВА 11 обов’язкового марксизму-ленінізму), програмування, як процес впорядковування хаотичної інформації, руйнує Карму. А це, як відомо, відображається на успіхах, на здоров’ї, на дітях і на наступному житті. Проте, напевно, відмова від програмування через лінь і нецікавість руйнує Карму ще сильніше. Є над чим поміркувати”. Доповнює картину Брукс [14], аналізуючи позитивні і негативні аспекти програмування: Радощі програмування. Безперечно, програмування формує і розвиває здатність людини логічно мислити. Воно є інструментом розвитку людського інтелекту. Чому програмування приносить задоволення? Як винагороджуються зусилля професіонала? 1. Це абсолютна радість творчості. Як дитина радіє, ліплячи пиріжки з піску, так і дорослий насолоджується процесом створення речей, особливо, якщо він сам їх вигадує. Мені здається, що прообразом цієї радості творчості слугує те задоволення, з яким Всевишній займався створенням світу і яке знайшло своє віддзеркалення в оригінальності та красі кожного листочка, кожної сніжинки. 2. Це радість створення речей, корисних іншим людям. Десь у глибині душі ми хочемо, щоб інші люди використовували нашу роботу і вважали її корисною. У цьому сенсі результат роботи програміста не дуже відрізняється від першої дитячої підставки для олівців “в подарунок татові”. 3. Це чарівність, закладена в самому процесі створення складних, загадкових об’єктів, що складаються з взаємозв’язаних, непостійних частин, і спостереження за тим, як вони працюють у заплутаних циклах, зберігаючи вірність принципам, закладеним у них із самого початку. Обчислювальна машина володіє привабливою силою більярда або музичного автомата, доведених до логічної завершеності. 4. Це можливість постійно вчитися, яка випливає із характеру задачі, що неперервно змінюється. У тому або іншому розумінні проблема виявляється новою. А людина, яка її вирішує, набуває нових знань, іноді теоретичних, іноді практичних, а іноді - тих та інших водночас. 5. Це задоволення працювати з дуже гнучким матеріалом. Програміст, як поет, працює майже виключно головою. Він
12 ПЕРЕДМОВА будує свої замки в повітрі і з повітря тільки силою своєї уяви. Надто рідко матеріал для творчості передбачає таку гнучкість, таку можливість частих покращень і переробок і такими простими засобами дає змогу здійснити величезні задуми. Проте, як ми побачимо згодом, ця гнучкість породжує свої проблеми. Матеріал поета - слова, і результат - ті ж слова. Програміст, на відміну від поета, створює програмний продукт, реальний у тому сенсі, що сам програміст рухається і працює, продукуючи видимий результат, відмінний від нього самого. Він друкує результати, креслить малюнки, генерує звуки, управляє рухом руки. Чари міфів і легенд сьогодні стали дійсністю. Ви набираєте на клавіатурі закляття, і ось екран дисплея оживає, показуючи об’єкти, яких не було і ніколи не могло бути. Програмування дарує нам радість тому, що дає змогу задовольнити прагнення до творчості, глибоко закладене в нас, і розділити це відчуття радості з іншими. Недоліки програмування. Далеко не все у програмуванні тішить програміста, і виявлення недоліків, властивих його ремеслу, дає змогу швидше з ними впоратись. 1. Працювати потрібно дуже ретельно. У цьому значенні ЕОМ також нагадує чаклунство з казок. Якщо хоч один символ, один пропуск у магічній формулі не перебуватиме строго на своєму місці, магія не спрацює. Люди не звикли до досконалості, і лише деякі зі сфер людської діяльності вимагають її. 'Звикання до вимог досконалої точності є, на мою думку, найважчим у процесі навчання програмуванню. 2. Задачі, що стоять перед програмістом, визначають інші люди, вони ж надають йому ресурси, забезпечують інформацією. Одна людина украй рідко сама визначає умови своєї роботи, не кажучи вже про її цілі. В адміністративних термінах це означає, що ступінь відповідальності перевищує об’єм прав. Проте, мабуть, в усіх областях творчої діяльності формальний об’єм прав ніколи не узгоджується з відповідальністю. Насправді ж фактичний об’єм прав досягається, як тільки роботу завершено. Залежність від інших виявляється тут надто болісно для системного програміста. Він залежить від чужих програм. Водночас ці програми, здебільшого, неправильно спроектовані, погано реалізовані, не цілком
ПЕРЕДМОВА 13 укомплектовані (наприклад, немає тексту програми на вхідній мові або немає тестів для її перевірки) і слабо документовані. Отож, програмістові доводиться годинами розбиратися в таких речах,* які, в ідеалі, повинні бути цілком завершеними, доступними і легкими в користуванні. 3. Приємно видавати грандіозні ідеї, однак якою насправді “пекельною працею” іноді стає пошук найдрібнішої помилки! Творча діяльність вимагає довгих годин кропіткої і нудної праці. Програмування, у цьому сенсі, не виняток. 4. Може видатися, що чим менше помилок у програмі, тим легше їх відшукати, тобто швидкість налагодження наче володіє квадратичною збіжністю. У житті все навпаки - збіжність виявляється лінійною або ще гіршою, тобто виявлення останніх помилок у процесі налагодження вимагає значно більше часу, ніж виправлення перших. 5. Остання неприємність, останнє розчарування полягає у тому, що продукт, над яким Ви працювали так довго, на момент завершення (або ще раніше) вже застарів. Завжди суперники шукають нові, ще кращі ідеї, а виношену Вами ідею хтось уже не тільки придумав, але й почав розробляти. Дійсність, зазвичай, є менш страшною. Новий, начебто кращий продукт, здебільшого, ще не є доступним на момент, коли Ви вже завершили свій власний; про нього досі тільки говорять. На його створення теж потрібно затратити місяці праці. Паперовий тигр не суперник реальному, якщо йдеться про його використання. Зазвичай, технічна база, на якій все побудовано, поступово рухається вперед. Як тільки проект остаточно прийнято, він стає застарілим у значенні своїх концепцій. Однак здійснення проекту, спрямованого на отримання реального продукту, вимагає часу і праці. Ступінь відсталості реалізованого проекту потрібно вимірювати відповідно до інших існуючих реалізацій, а не щодо нереалізованих досі концепцій. Мета і завдання полягають у тому, щоб знайти реальні рішення реальних проблем відповідно до існуючих планів і наявних ресурсів. Таке програмування - водночас і асфальтова драговина, яка поглинає чимало ідей, і творча діяльність з властивими тільки їй радощами і смутком. В очах багатьох її радощі все-таки значно переважають жалі...” [14]. Філософія програмування. Комп’ютер дає змогу людині створювати щось нове, цікаве, корисне, застосовуючи потужні
14 ПЕРЕДМОВА засоби математики, фізики та інших природничих наук. Дає змогу моделювати з допомогою формул і математичних перетворень поведінку об’єктів реального світу та отримувати з цього, окрім потрібної інформації, задоволення, яке можна порівняти з мистецтвом. З допомогою комп’ютера можна відображати істину в художньому оформленні, в чуттєвій формі. А це і є мистецтвом. Чим вважати програмування - мистецтвом чи ремеслом - обговорюють у літературі десятиліттями [7, 14, 61, 83]. Коли кравчиня щодня шиє одяг, то це, зазвичай, ремесло. Проте роботи відомих модельєрів сприймають як витвори мистецтва. Не варто вважати, що масовий пошив - ремесло, а окрема модель - це вже мистецтво. Шевченкові вірші також написано в одному рукописному примірникові. Проте їхнє тиражування у мільйонах примірників упродовж останніх півтораста років не знизили їхнього мистецького та художнього рівня. Далеко не кожен вірш, скульптуру чи жіноче плаття вважають витворами мистецтва. Все залежить від особистості їхнього творця, рівня його майстерності та геніальності. Якщо під час написання програми автор-професіонал вклав у неї свій досвід, майстерність та душу - вона стає витвором мистецтва і слугує людям тривалий час. Прикладом є геніальний витвір Ніклауса Вірта - Ряяса/; чи Лінуса Торвальдса - Ьіпих. Хто цікавиться проблемами моделювання динаміки фізичних систем, знає програму ВІРБиВ та її автора - Гіра [114]. Таких прикладів можна навести безліч.* Виняткове значення набуває комп’ютерна творчість з виникненням сучасних засобів комп’ютерної графіки. Програміст-творець отримав інструмент, який дає змогу втілити у графічні образи політ його технічної думки, його фантазії і продемонструвати їх широкій аудиторії. “Якби програмування не носило в собі елементів творчості, займатися ним було б нудно. Уявіть собі: вісім годин в день перед очима монітор, заповнений нескінченним ланцюжком символів. Вам би це обридло, чи не так? І тут йдеться не про гроші, а про ту віддачу, яка допомагає нам займатися своєю роботою від відпустки до відпустки. Якби програмісти не відчували морального задоволення від своєї діяльності, вони б просто вимерли”[83]. Автор, якого ми процитували, дотепно аналізує не тільки подібність програмування до творчості, але й специфіку цього процесу. Програмування не використовує рефлекторність у ролі
ПЕРЕДМОВА 15 методу пізнання. Поет чи художник у творчому процесі вирішують власні душевні проблеми. Програміст, створюючи програмний продукт, відволікається від життєвих переживань, забуває про свої негаразди. З іншого боку, програміст творить як митець, а результати його роботи оцінюють як ремесло. Хіба може користувач-непрограміст збагнути, скільки душевної енергії вкладено у те, щоб програма працювала правильно та ефективно? У програмуванні відсутнє поняття плагіату. Існує безліч стандартних бібліотек програм у відкритому доступі, дозволених для використання за будь-яких умов. Програму, яка використовує фрагменти відкритого коду для розв’язання складної задачі, вважають цілком самостійною. Аби тільки добре працювала! Залежно від особи, яка створює програму, остання буде відображати світосприйняття її творця. Одна людина створює цікаві, корисні програми, які володіють зручним і дружнім інтерфейсом, програми, які дають змогу отримувати позитивні знання. Інша - весь свій досвід та інтелект спрямовує на створення програми, яка знищує чужу інтелектуальну власність, чужі знання і здобутки. Згадаймо, скільки за останні десятиліття створено комп’ютерних вірусів, здатних до саморозмноження і знищення результатів чужої праці. Комп’ютер у сучасному світі відіграє роль потужного та ефективного засобу пізнання, навчання і виховання. Проте складність і незрозумілість принципів дії комп’ютера для середньостатистичного користувача слугує, здебільшого, причиною безумовної довіри до інформації, отриманої з комп’ютера, віри у безпомилковість його результатів. Це перетворило комп’ютер на рекламний інструмент, на засіб астрологічних прогнозів чи діагнозів. На превеликий жаль, не враховано, що діагностуючі чи прогнозуючі програми написано людьми, а не якимось вищим розумом. Отож, у них можливі помилки, а також свідомо закладені елементи ошуканства, яким не варто надто довіряти. Сказане значною мірою стосується даних, які знаходимо у мережі ІШетеї. Створено величезну кількість ігрових комп’ютерних програм, в основу яких покладено насильство і жорстокість. Передусім, це особливо згубно впливає на свідомість підлітка, який може годинами віртуально вбивати своїх супротивників, не усвідомлюючи, що в житті аналогічна поведінка спричинить до каліцтва чи трагедії. Подібні програми травмують психіку дитини.
16 ПЕРЕДМОВА Рідко вони є корисними і для дорослої людини. Прогрес комп’ютерних відеосистем спричинює до того, що “віртуальна реальність” стає все реалістичнішою. Отож, людині, яка захопилась сучасною комп’ютерною грою, все важче повернутись до нормального сприйняття дійсності з її проблемами, цінностями і законами. Людина занурюється у сюрреальний світ фантазій, який стає для неї своєрідним психологічним наркотиком чи запоєм. Ілюстрацією сказаного є популярність електронних істот - тамагочі - іграшок з дисплейчиком і кнопками управління. Програма, яку закладено у мікропроцесор, розташований всередині іграшки, створює ілюзію того, що іграшка є живою. Її потрібно електронним способом годувати, розважати, лікувати та доглядати. Ця іграшка може віртуально зростати, бути веселою і щасливою або захворіти і померти. Отож, дитина отримує спрощений і перекошений сурогат живої істоти, відношення до якої замінює розвиток у неї відчуття любові до ближнього та адекватне сприйняття життєвих цінностей. Відомі випадки, коли дитина, доручаючи догляд за іграшкою своїм батькам, була ладна вбити останніх, якщо з їхньої провини тамагочі “померло”. Життя засвідчує, що робота з комп’ютерними програмами не тільки здатна впливати на психіку користувача, а й на психіку їхнього творця - програміста. За тривалого спілкування з машиною людина розпочинає мислити її категоріями. З одного боку, це позитивно. Ми переконані, що програмування, як і математику, необхідно вивчати хоча б для того, “що воно розум у порядок приводить”. Програмування виробляє у людини алгоритмічний спосіб мислення, вчить прогнозувати наслідки своєї діяльності. Це є корисним, передусім, при управлінні людськими колективами, взаємодія між якими подібна до роботи програмної системи, яка складається зі значної кількості підпрограм, що обмінюються з допомогою спеціальних інтерфейсів результатами своїх обчислень. Однак програміст іноді настільки зосереджується на вирішенні машинних проблем, що переносить комп’ютерні категорії на людське оточення. Згадаймо беконечні історії та анекдоти про “справжніх” програмістів...
ВСТУП Комп’ютерні технології інтенсивно проникають як у прикладну, так і в теоретичну фізику. Широкий спектр математичних і спеціалізованих пакетів, які можна використати для розв’язання на комп’ютері фізичних задач, не заперечують, а, навпаки, демонструють необхідність глибокого розуміння методів, які в них закладено. Можна перелічити чимало підручників і монографій, у яких, з різним ступенем деталізації, описано теорію методів обчислювальної математики [18, 32, 33, 43, 48, 71, 82, 85, 108]. Існує також безліч публікацій (електронних і паперових), в яких ці методи реалізовано як програми, написані різними мовами програмування [23, 49, 58, 70, 102, 103, 112]. Проте практично відсутні книги, які б містили детальні алгоритми реалізації чисельних методів у формі чітких і однозначних інструкцій, як із певного набору формул отримати працездатну, універсальну, оптимальну комп’ютерну програму. Маємо надію, що наш підручник частково заповнить цю нішу. Автор є свідомий того, що написати підручник так, щоб він сподобався і був зрозумілий усім - неможливо. Мета підручника - навчити, тобто передати студенту певний набір ідей, а це означає, що в підручнику ці ідеї повинні бути присутніми, проте їх не повинно бути забагато. З іншого боку, успіх підручника залежить від того, чи ідеї, які у ньому наявні, когось цікавлять, чи вони є актуальні і корисні. Форма та стиль представлення цих ідей також відіграє не останню роль. Тому в книзі багато виділень жирним шрифтом, курсивом, рамочками. Так ми намагаємось звернути увагу на головне. Для кого цей підручник призначено? Для студентів молодших курсів, які вивчають основи програмування практично з
18 ВСТУП нуля. Обов’язок автора передбачити труднощі читача і намагатись позбавити останнього від них, а не заводити читача в оману. Програмування вимагає вродженого таланту, проте навіть найталановитіший програміст не народився зі знанням тонкощів своєї професії. Ці знання він отримав у результаті двох чинників: навчання і багаторічної практики. Підручник призначено для навчально-методичного забезпечення процесу вивчення студентами-фізиками курсу “Програмування і математичне моделювання”. Цей курс передбачає засвоєння правил і прийомів програмування мовою РаБсаІ, опанування математичними основами обчислювальної математики, та виконання серії лабораторних робіт, більшість з яких полягають у розв’язанні простих задач чисельними методами. Сподіваємось, що він буде корисний також і студентам інших відповідних спеціальностей вищих та середніх навчальних закладів. Методикою виконання робіт передбачено, що після прослуховування та опрацювання лекційного матеріалу (в поза- аудиторний час) студент досліджує відповідний алгоритм і пише мовою Вогіапй РаБсаІ (ВР) їхню програмну реалізацію. В обчислювальній лабораторії студент вводить програму, налагоджує її і досліджує на тестових прикладах. У цьому випадку досягається подвійний результат: студент вивчає як особливості класичних методів комп’ютерного розв’язання фізичних задач, так і раціональні прийоми програмування задач цієї предметної сфери. Виконуючи завдання лабораторного курсу, студент поглиблюватиме свої знання у таких розділах мови ВР, як графіка, файли, робота з масивами, глибше опанує використання власних і стандартних процедур, функцій і модулів. Матеріал підручника викладено з урахуванням системного підходу: всі алгоритми виконано в одному стилі із дотриманням єдиної системи умовних позначень, що значно спрощує роботу як студента, так і викладача, який проводить заняття. На сайті факультету електроніки ЛНУ імені Івана Франка можна знайти тексти усіх програм та їх алгоритми, які наведено у підручнику, а також інші корисні матеріали: лvww.electronics.wups.lviv.ua:8102/arhiv/books/Electronic_Library/XIO_PMM.zip Автор наперед вдячний за всі критичні зауваження та побажання, стосовно змісту підручника, які Ви можете надсилати за адресою: khvyschun@electronics.wups.lviv.ua
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 1.1. Сутність програмування Під програмуванням розуміємо опис процесів обробки даних на комп’ютері. Дані (data) - це представлення фактів та ідей у формалізованому вигляді, яке є придатним для здійснення самого процесу обробки. Інформація (information) - це зміст, який надається даним під час їхнього відображення. Обробка даних (data processing) - це виконання систематичної послідовності дій з даними. Дані відображаються і зберігаються на відповідних носіях. Сукупність носіїв даних, яку використовують під час обробки даних, називають інформаційним середовищем. Набір даних, що міститься у деякий момент в інформаційному середовищі, назвемо станом цього інформаційного середовища. Процес обробки даних можна означити як послідовність станів певного інформаційного середовища. Описати процес - означає задати послідовність станів деякого інформаційного середовища. Якщо ми хочемо, щоб за заданим нами описом необхідний процес генерувався на будь-якому комп’ютері автоматично, необхідно, щоб цей опис був формалізованим. Формалізований опис називають програмою. Очевидно, що програма повинна бути зрозумілою не тількц комп’ютеру, але й людині, оскільки і під час розробки програм, і під час їхнього застосування доводиться аналізувати, який саме процес вона породжує. Отож, програму записують на зручній для
20 1.1. Сутність програмування людини формалізованій мові програмування, з якої вона автоматично перекладається на мову відповідного комп’ютера за допомогою іншої програми - транслятора. Людині (програмістові), перш ніж скласти програму на зручній для нього мові програмування, доводиться проробляти чималу підготовчу роботу з уточнення постановки задачі, вибору методу її рішення, зі з’ясування специфіки застосування необхідної програми, з прояснення загальної організації програми, що розробляється, і багато іншого. Використання цієї інформації може істотно спростити задачу розуміння програми, отож, вельми корисно її якось фіксувати як окремі документи (часто не формалізовані, розраховані тільки на сприйняття людиною). Зазвичай, програми розробляють з розрахунку на те, щоб ними могли користуватися ті, хто не бере участь в їхній розробці (ікористувачі). Для розуміння програми користувачем, окрім її тексту, потрібна певна додаткова документація. Програму, або логічно зв’язану сукупність програм, забезпечену програмною документацією, називають програмним засобом (ПЗ). Програма дає змогу здійснювати деяку автоматичну обробку даних на комп’ютері. Програмна документація дає змогу зрозуміти, які функції виконує та чи інша програма, як підготувати початкові дані і запустити необхідну програму в процес її виконання, а також: що означають одержані результати (або який ефект виконання цієї програми). Окрім того, програмна документація допомагає розібратися в самій програмі, наприклад, для її модифікації чи адаптації до власних потреб. Отже, результатом застосування технології програмування, її продуктом є ПЗ, який складається із програм, що виконують потрібні функції. Щодо цього вважатимемо, що програма не містить помилок {software error). Кажуть, що програма має помилку, якщо вона не видає очікуваних користувачем результатів. Про те, які саме дії виконує програма, користувач дізнається з документації на зазначений програмний продукт. Установлення факту наявності помилки у програмі досягається її тестуванням. Щоб переконатись у тому, що програма не має помилок, розробляють систему тестів, яка дає змогу виявити значну кількість помилок, однак у жодному випадку не довести, що помилок зовсім не існує. У складному алгоритмі вкрай важко протестувати всі можливі варіанти його роботи. Отож,
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 21 завжди існує ймовірність того, що виникне ситуація, за якої програма видасть помилковий результат, тобто виявиться неправильною. Альтернативою правильності ПЗ є поняття його надійності. Надійність (reliability) ПЗ - це його здатність безвідмовно виконувати певні функції за заданих умов протягом заданого періоду часу з достатньо великою вірогідністю. Під відмовою ПЗ розуміють виникнення у ньому помилки. Отже, надійний ПЗ не виключає наявності в ньому помилок - важливо лише, щоб ці помилки під час практичного застосування цього ПЗ у заданих умовах виявлялися не надто часто. Переконатися, що ПЗ володіє такою властивістю, можна під час його випробування шляхом тестування, а також під час практичного застосування. Отже, фактично ми можемо розробляти лише надійні, а не цілком правильні програми. ПЗ може володіти різним ступенем надійності. Як виміряти цей ступінь? Як в техніці, ступінь надійності можна характеризувати вірогідністю роботи ПЗ без відмови протягом певного періоду часу. Під час оцінювання ступеня надійності ПЗ необхідно враховувати наслідки кожної відмови. Одні помилки в ПЗ спричинюють лише деякі незручності під час його застосування, інші можуть мати катастрофічні наслідки, наприклад, загрожувати людському життю. Отож, для оцінки надійності ПЗ іноді використовують додаткові показники, що враховують вартість завданої шкоди для користувача кожною відмовою. При розробці ПЗ розрізняють два поняття: • технологія програмування (programming technology) - сукупність процесів з розробки ПЗ, які складаються з методів та інструментальних засобів, які передбачають створення необхідних програм; • методологія програмування (programming methodology) - сукупність підходів, які застосовуються в процесі розробки ПЗ та об’єднані одним спільним філософським принципом. У літературі використовують близьке до технології програмування поняття програмна інженерія (software engineering). Під цим поняттям розуміють систематичний підхід до розробки, експлуатації, супроводу і вилучення з обігу програмних засобів. Головна розбіжність між технологією програмування і
22 1.1. Сутність програмування програмною інженерією, як дисциплінами для вивчення, полягає у способі розгляду і систематизації матеріалу. У технології програмування увагу акцентують на вивченні процесів розробки ПЗ (технологічних процесів) і порядку їхнього протікання. Вивчаються методи та інструментальні засоби розробки ПЗ, які використовують у цих процесах. Застосування таких методів формує технологічний процес. У програмній інженерії вивчають різні методики та інструментальні засоби організації розробки ПЗ для досягнення певної мети. Ці методи і засоби можуть використовуватися в різних технологічних процесах (і в різних технологіях програмування). У програміста-початківця іноді виникає враження, що він є гвинтиком величезної машини: йому необхідно використовувати нав’язані кимось мови програмування, системи та інструменти, виконувати завдання, які могли бути зроблені до нього і за нього. Проте, здебільшого, його роботу оцінюють по тому, що і скільки він здатен зробити з допомогою доступних йому засобів.
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 23 1.2. Мови програмування. Коротка історія Мова є засобом спілкування між людьми. Якщо співрозмовники не володіють спільною мовою, вони вдаються до послуг перекладача, щоб зрозуміти один одного. Назвемо мовою систему запису, призначену для передачі певного змісту. Хоча комп’ютер і є витвором людського розуму та рук, його "мозок” - центральний процесор (ЦП) - безпосередньо сприймати команди, подані людським голосом, ще не здатний. ЦП виконує команди, кожна з яких є послідовністю електричних імпульсів двох рівнів амплітуди. Один з цих рівнів інтерпретується як “нуль” (“0”), інший - як “одиниця” (“1”). Тобто ЦП обробляє дані, закодовані у двійковій системі числення. Найперші електронно-обчислювальні машини (ЕОМ) програмували шляхом набору на спеціальних пультах, з допомогою перемикачів або металевих пластинок з отворами, машинних команд у двійковому вигляді. Програмування тоді було справою вкрай обмеженої кількості утаємничених фахівців. Першим кроком до спрощення процесу введення програми у пам’ять машини стала розробка Автокоду, який дав змогу кожну машинну команду представляти набором цифр вісімкової системи числення. Кожній цифрі з діапазону 0.. 7 відповідала трійка (тріада) нулів та одиниць. Таблиця 1.1 Кодування у двійковій системі числення цифр вісімкової системи 0->000 1 —>001 2->010 3->011 4->100 5->101 6—> 110 7 —> 111 Згодом машинні команди почали кодувати, використовуючи шістнадцяткову систему числення. Кожній шістнадцятковій цифрі тут ставилась у відповідність четвірка {тетрада) нулів і одиниць. Табтщя1.2 Кодування у двійковій системі числення цифр шістаадцяткової системи 0->0000 1 ^ 0001 2->0010 3 -> 0011 4 —» 0100 5->0101 6->0110 7 -> 0111 8 -> 1000 9->1001 А -> 1010 В-> 1011 С —> 1100 О->1101 Е -» 1110 Г-> 1111
24 1.2. Мови програмування. Коротка історія Машинна команда складалась із коду операції (КОП) і одного, двох чи трьох операндів, які вказували розташування аргументів в оперативній пам’яті і місце запису результату виконання цієї команди. Машинні команди, подані подібним способом, наносили (перфорували) на паперові носії (перфострічки, перфокарти). Двійковій “1” відповідав круглий або прямокутний отвір. Відсутність отвору сприймалась як “0”. Аналогічно кодувались і перфорувались цифрові дані, що підлягали обробці. Перед початком роботи, з допомогою електронно-механічних читаючих пристроїв, програму вводили в оперативну пам’ять машини. Наступним етапом спрощення роботи програмістів стала розробка Асемблерів - програм, що передбачали кодування машинних команд не у цифровій, а в легшій для сприймання, символьній формі. У цьому випадку і коди операцій, і операнди отримували свої унікальні змістовні (мнемонічні) імена. Процес перетворення такої програми у машинні коди здійснював Асемблер. Наприклад, на Автокоді команда додавання двох чисел, розташованих в ОП записувалась так (для ЕОМ ІВМ/370): КОП 2 операнда - адреси аргументів Шістнадцяткова форма-» ЕА 12 С0 0 0 С 0 0 8 Її двійковий аналог—» 11111010 0001001011000000000000001100000000001000 В Асемблері ця команда мала вигляд |ар еьра, ПмР^, до ар - назва команди додавання, гам. і еі*рв - імена першого і другого операндів, відповідно. Результат її виконання записувався на місце першого операнда. Примітка. У літературі з програмування інколи трапляється помилковий термін “мова Асемблера”. Такої мови не існує. Асемблер не генерує програму в машинних кодах на основі алгоритму, який записано мовою, близькою до людської, а лише здійснює перекодування символьних імен кожної команди у їхні двійкові аналоги. При програмуванні на Асемблері роль компілятора виконує людина-програміст. Революцією у програмуванні стало створення мови програмування високого рівня - системи засобів і стандартів, які дали змогу записати машинні алгоритми мовою, близькою до
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 25 людської: з допомогою літерно-словесних речень, якими задано правила введення, обробки і відображення у символьній чи графічній формі результатів обчислень. У цьому випадку здійснюють запис складних математичних виразів у звичній для людини алгебричній формі. Такі засоби автоматизації праці програміста названо мовами програмування високого рівня. Низькорівневим програмуванням вважають програмування в Асемблері. Першою мовою програмування високого рівня став Fortran (Formula Translation), який розроблено у 1956 році співробітниками фірми IBM під керівництвом Бекуса. Впродовж наступних років і до сьогодні її використовують для розробки ефективних програм у науково-технічній галузі. У 1958—60 pp. група на чолі з Вайнгартеном розробила мову Algol-60. Вона володіла систематичною структурою і чітким визначенням, оскільки її розроблено фахівцями з обчислювальної математики і для фахівців у цій області. Цій мові бракувало компіляторів і промислової підтримки, однак її високо оцінено тими, хто мав математичну підготовку. Щоб отримати визнання мови Algol-60, довелось розширити її область застосування. Група розробників намагалась вирішити це питання шляхом розробки мови- спадкоємця, проте розділилася на два табори. Одні мали намір встановити окрему віху на шляху розробки мов, інші відчували, що часу обмаль, а відповідне розширення Algol-60 було би вкрай корисним. Представниками цього другого табору були Тоні Хоар і майбутній автор мови Pascal Нікгшус Вірт. Саме ними на першій версії машини IBM 360 Стенфордського університеїу реалізовано варіант мови, який згодом став відомим як ALGOL W і використовувався в декількох університетах з навчальною метою. Головний недолік цієї мови - непридатність на роль інструмента для системного програмування. Розмір компілятора ALGOL W виріс за межі, які можна охопити по думки, щоб зрозуміти всю програму. Бажання домогтися суворішого і, водночас, відповіднішого щодо системного програмування формалізму не було задоволено. Не було досягнуто цього і в майбутній універсальній мові PL/1. У 1960 році жінка-програміст Грейс Мюррей Хопер, майбутній адмірал BMC СІЛА, створила мову програмування надвисокого рівня COBOL (Common Business Oriented Language - мова для економічних задач). Перегляд прикладного програмного забезпечення, здійснений 1996 року у зв’язку з проблемою 2000, засвідчив, що у світі не менше 70% промислового програмного забезпечення написано саме цією мовою. Половина програмістів- професіоналів СІЛА сьогодні працює на ній. Сучасні компілятори COBOLy, що враховують нові віяння (Visual-засоби, об’єкти, И^-програмування та ін.), існують практично для всіх платформ і операційних систем. Якщо врахувати, що цією мовою написано також перші емулятори системи команд бортових обчислювальних пристроїв, призначених для керування торпедним і ракетним вогнем з атомних підводних човнів СІЛА, та безліч інших програм, спрямованих на руйнування економіки потенційного супротивника, то інтерпретація назви може сприйматися як специфічний жарт. Проте програмні
26 1.2. Мови програмування. Коротка історія засоби COBOLy виявилися настільки гнучкими, ефективними й універсальними, що саме з нього вийшло чимало систем управління базами даних (СУБД), генераторів звітів, іншого інструментарію, який дійсно широко застосовують у комерційній сфері. Задовго до виникнення Ititernet у COBOL вбудували п’ять операторів, які давали змогу працювати з електронною поштою. Тільки опис концепцій сучасного COBOLy займає близько 1000 сторінок. Разом з тим COBOL не претендує на роль універсальної мови програмування. Його ніша - розробка великих і надвеликих проектів (багато мільйонів рядків вихідного тексту) обробки даних; причому дані можуть мати структуру практично необмеженої складності. У 1964 році здійснено спробу створити універсальну мову програмування, яка б об’єднувала у собі все краще, що було того часу у мовах Fortran, Algol і COBOL. Так виникла мова PL/1. Ідея створення мови “на всі випадки життя” була сумнівною. Мова вийшла не зовсім вдалою. За словами Вірта, ідея “єдиного ножа для швейцарської армії” має свої переваги. Та коли її довести до абсурду, цей “ніж” перетворюється у камінь на шиї. Правила мови виявились доволі складними. Програми, написані цією мовою, виходили повільними і неефективними, що спричинило занепад PL/1. У 1972 році Деніс Рітчі розробив одну із найпопулярніших сьогодні мов програмування - мову Сі. Кожна із п’яти перелічених мов була призначена для професійного програмування фахівцями-програмістами. Зростання кількості ЕОМ на початку 70-х років спричинило до масового використання обчислювальної техніки. Виникла необхідність розробки мов програмування, зручних, передусім, для навчання дітей, основних ідей і правил розробки програм. Наприкінці 60-х років С. Пейперт розробив навчальну мову LOGO, яка розвивала алгоритмічний спосіб мислення, використовуючи графічні методи. Проте значного розповсюдження у вітчизняних школах вона не знайшла. Наймасовішою навчальною мовою програмування став BASIC (Beginner's All-Purpose Symbolic Instruction Code - мова символічних інструкцій широкого призначення для початківців), створений 1964 року викладачами Дартмутського коледжу Джоном Кемені і Томасом Курцем для ознайомлення студентів з обчислювальною технікою. Для перших ПК BASIC слугував як мовою програмування, так і операційною системою. Згодом його вдосконалені версії широко використовували як для навчальних цілей, так і для розв’язання практичних задач невисокого рівня складності. Вперше BASIC застосовано у комп’ютері IBM 704, проте широке розповсюдження він отримав на початку 1980-х, після того, як у 1975 р. Біл Геіипс і Пол Ален написали інтерпретатор BASIC для першого ПК Altair 8800. Розвиток програмування як науки, виникнення методологій структурного, модульного і, передусім, об’єктного програмування спричинило до того, що BASIC став гальмом у розвитку ідей програмування і почав поступово здавати свої позиції на користь мови Pascal, яку ми і вивчатимемо впродовж нашого курсу. Зауважимо, що трансформований BASIC (Visual Basic) широко використовують для побудови прототипів програм на фірмі MicroSoft. Біл Гейте вимагає від розробників нових ідей спочатку впроваджувати їх на BASIC у, а тільки згодом - на швидшій і кращій мові.
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 27 1.3. Компілятори, інтерпретатори, лінкери, завантажувачі Мова програмування містить набір суворих правил, виконання яких забезпечує однозначне відтворення алгоритму розв’язання певного класу задач. Звичайна розмовна мова складається з чотирьох базових елементів: алфавіту, слів, словосполучень і речень. Алгоритмічна мова вміщає подібні елементи, тільки слова називають елементарними конструкціями, словосполучення - виразами, а речення - операторами. Алфавіт, елементарні конструкції, вирази й оператори формують ієрархічну структуру, оскільки елементарні конструкції утворюються з послідовності символів алфавіту, вирази - це послідовність елементарних конструкцій і символів, а оператор - послідовність виразів, елементарних конструкцій і символів. Опис мови є описом чотирьох перелічених елементів: • опис алфавіту полягає у переліку допустимих символів мови; • під описом елементарних конструкцій розуміють правила їхнього утворення і використання; • опис виразів - це правила утворення будь-яких виразів, що мають зміст у певній мові; • опис операторів складається з розгляду всіх типів операторів, допустимих у мові. Опис кожного елемента мови задається його синтаксисом і семантикою. Синтаксичні визначення встановлюють правила побудови елементів мови. Семантика визначає зміст і правила використання тих елементів мови, для яких подано синтаксичні визначення. Алфавіт мови - це чітко визначений набір неподільних символів, за допомогою яких записують всі конструкції програми. Елементарні конструкції - це мінімальні одиниці мови, що мають самостійний зміст. Вони утворюються з символів алфавіту мови. Вираз в алгоритмічній мові складається з елементарних конструкцій і символів і задає правило обчислення деякого значення.
28 1.3. Компілятори, інтерпретатори, лінкери, завантажувачі Оператор задає вичерпний опис деякої дії, яку необхідно виконати. Для опису складної дії може знадобитися група операторів. У цьому випадку оператори об’єднуються в складний оператор {блок). Дії, задані операторами, виконуються над даними. Речення алгоритмічної мови, у яких подають відомості щодо типів даних, називають описами або невиконуваними операторами. Об’єднана єдиним алгоритмом сукупність описів і операторів утворює програму, написану алгоритмічною мовою. У процесі вивчення алгоритмічної мови необхідно відрізняти алгоритмічну мову від тієї мови, за допомогою якої здійснюють опис певної алгоритмічної мови. Зазвичай, досліджувану мову називають просто мовою, а мову, у термінах якої подано опис досліджуваної мови - алгоритмом. Синтаксичні визначення можна задати формальними чи неформальними способами. Існує три формальні способи: • металінгвістична символіка, яку називають формулами Бекуса-Наура; • синтаксичні діаграми; • дужкові конструкції. Перетворення програми, написаної мовою програмування високого рівня, до її машинного аналогу відбувається у декілька етапів: Транслювання - перетворення (переклад) тексту програми в набір машинних команд {об'єктний код). Транслювання виконують спеціальні програми - транслятори. Транслятори бувають двох типів: компілятори та інтерпретатори. Компілятор обробляє програму як єдине ціле, виконуючи чотири послідовні кроки: а) лексичний аналіз - пошук і виокремлення у тексті синтаксичних одиниць: ключових слів, числових значень, імен змінних, імен підпрограм та ін.; б) синтаксичний аналіз - поділ програми на окремі синтаксичні конструкції та видачу повідомлень щодо наявності синтаксичних помилок; в) генерування об’єктного коду згідно із синтаксичними конструкціями; г) оптимізування цього коду за швидкодією та за об’ємом необхідної для його роботи оперативної пам’яті.
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 29 Інтерпретування - це пооператорний переклад програми з можливістю контролю і зміни значень кожної змінної в процесі роботи. Очевидно, що інтерпретатори створюють неоптимальний об’єктний код, проте спрощують розробку програми, даючи змогу змінювати її оператори в процесі інтерпретування. Транслятори таких мов, як Fortran, Pascal, Сі - компілюючого типу, a BASIC - інтерпретуючого. Зауважимо, що сучасні компілятори передбачають покрокове виконання програми (режим налагодження), а останні версії мови BASIC забезпечують також режим компілювання. Лінкування (Linking) - процес об’єднання окремих частин програми, які компілювались незалежно, та приєднання до них загальносистемних процедур, таких як процедури введення/виведення, обробки сигналів переривань від зовнішніх пристроїв комп’ютера та ін. Завантаження - настроювання коду програми перед її виконанням на адреси тієї ділянки ОП, в яку її завантажуватимуть. 1.4. Поняття інформації. Властивості інформації У 1946 р. американський вчений-статистик Джон Тьюкі запропонував назву біт (ВІТ - абревіатура від Binary digiT), яка стала одним із головних понять XX століття. Тьюкі позначив цим терміном один двійковий розряд, що може набувати значення 0 або 1. Клод Шенон використав біт як одиницю вимірювання інформації. Мірою кількості інформації Шенон запропонував вважати функцію, яку він назвав ентропією. Термін інформація (від лат. informatio - відомості) має безліч значень, отож, його неможливо чітко визначити. Найчастіше під інформацією розуміють відображення об’єктів матеріального світу у формі сигналів і знаків. В інформатиці за цим поняттям стоять відомості щодо об’єктів і явищ навколишнього середовища, їхніх параметрів, властивостей і стану. Ці відомості формують сутність знань про об’єкти, іцо досліджуються. Метою подібних досліджень є прийняття правильних рішень стосовно використання цих об’єктів чи облік і збереження інформації щодо них. Щоб інформація сприяла прийняттю на її основі правильних рішень,
ЗО 1.4. Поняття інформації. Властивості інформації вона повинна визначатися такими властивостями, як достовірність, вичерпність, актуальність, корисність, зрозумілість. Таблиця 1.3 Одиниці вимірювання інформації Кілобайт 2ю 1024 байт Мегабайт 220 1024 кілобайт = 1 048 576 байт Гігабайт 2зо 1024 мегабайт = 1 073 741 824 байт Терабайт 2^о 1024 гігабайт = 1 099 511 627 776 байт Петабайт 250 1024 терабайт = 1 125 899 906 842 624 байт Екзабайт 200 1024 пегабайт = 1 152 921 504 606 846 976 байт Зетабайт 270 1024 екзабайт = 1 180 591 620 717 411 303 424 байт Иотабайт 280 1024 зетабайт = 1 208 92 81 614 629 174 706 176 байт 1.5. Інформатика Інформатика відзначається переліком таких форм оперування інформацією: одержання, пошук, обробка (перетворення), передавання, відображення, а також її зберігання та захист. Одержання інформації належить до процедури створення нової інформації. Воно полягає в експериментальному дослідженні фізичних об’єктів чи явищ. Сюди можна зачислити методи спостережений, лічби, вимірювання, ідентифікації, діагностики, контролю, розпізнавання та випробування. Кожен цей метод реалізується як окрема процедура зі скінченною кількістю кроків. Спостереження є методом пізнання за допомогою людських органів чуття, які можуть бути оснащені спеціальними технічними засобами. Воно є складовою частиною усіх експериментальних методів пізнання і повинно задовольняти вимогам навмисності, систематичності, планомірності та цілеспрямованості. Лічба - це числове відображення кількісних властивостей деякої сукупності матеріальних предметів, що є якісно однорідними. Лічба базується на понятті одиниця. Число є множиною, яка складається з одиниць. Вимірювання - це відображення фізичної величини іменованим числом. Тут поєднується два методи пізнання: відтворення та порівняння. Уільям Кельвін стверджував, що кожна річ є відомою лише до тієї міри, до якої її можна виміряти. Фізичним процесом чи системою можна ефективно керувати тільки тоді, коли виміряно їхні базові параметри.
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 31 Ідентифікування - це встановлення залежності між параметрами, що характеризують матеріальний об’єкт, і його математичною моделлю. Щодо цього визначають тип моделі, її базові параметри, а також ступінь, точність і достовірність оцінки. Діагностика - це оцінка загального стану об’єкта з метою встановлення факту наявності чи відсутності відхилення його параметрів від нормальних. Розпізнавання - ототожнення досліджуваного об’єкта за сукупністю його властивостей з еталонним об’єктом з певної їхньої множини шляхом порівняння та аналізу характеристик вихідного об’єкта з характеристиками одного із попередньо класифікованих об’єктів зазначеної множини. Випробування - це вивчення стану досліджуваного об’єкта в момент дії на нього сукупності регламентованих чинників, і встановлення відповідності цього стану еталонному. Решта форм оперування інформацією стосується вже існуючої інформації. Технічне забезпечення цих форм сьогодні виконує комп’ютерна техніка. Пошук інформації здійснюється, як у друкованих, так і в електронних джерелах. Обробка інформації виконується програмними пакетами загального чи спеціального призначення. Передавання інформації між комп’ютерами здійснюється каналами зв’язку за допомогою локальних чи глобальних мереж. Каналом зв’язку може слугувати радіо, телефонна, оптоволоконна, супутникова чи інша лінія зв’язку. Відображення інформації здійснюється у текстовому, графічному чи звуковому варіанті з використанням як дисплеїв, так і паперу. Для зберігання інформації застосовують носії. Носій інформації - матеріальний об’єкт, який використовують для зберігання інформації. Носієм інформації може слугувати матеріальний предмет: папір, камінь, дерево, грифельна дошка; хвилі різної природи: акустична (звук), електромагнітна (світло, радіохвиля), гравітаційна (тиск, притягання); речовини у різному агрегатному стані (концентрація молекул в рідкому розчині, температура і тиск газу) тощо. Носій повинен бути зручним для нанесення та зчитування інформації, а також для зберігання і
32 1.5. Інформатика транспортування. У комп’ютерних інформаційних технологіях застосовують магнітні, оптичні та електронні носії. З метою захисту інформації від несанкціонованого доступу її шифрують. Щоб запобігти фізичному знищенню важливих даних, їх дублюють на додаткових носіях. Повідомлення м разом з відповідною йому інформацією L називають величиною. Інформацію L називають значенням величини, а повідомлення м називають позначенням величини. Щодо цього кажуть, що позначенню м відповідає значення L. Різним позначенням можуть відповідати одні і ті ж значення. Наприклад, позначенням VII, 7, 007 відповідає значення “сім”; позначенням 5.7, 005.700 - значення “п’ять цілих і сім десятих” тощо. В алгоритмах величини відіграють роль об’єктів, над якими виконуються певні операції. Множину величин, для яких визначено деяку множину операцій, називають множиною величин певного типу. Отже, тип величин визначається операціями, які над ними можна виконувати. Для посилання на величину використовують імена. З метою позначення імені використовують ідентифікатори. Позначення імені величини називають також позначенням величини. Величину, яка в будь-який момент часу може мати тільки одне значення, називають постійною, або константою. Величину, яка в будь- який момент часу може мати різні значення з деякої множини допустимих значень, називають змінною величиною. Проте в будь- який момент часу змінна величина може мати або тільки одне значення, яке називають поточним, або не мати жодного, якщо комірку, передбачену для зберігання значення змінної, ще не заповнено. Привласнення величинам значень виконується за допомогою команд присвоєння конкретної мови програмування. Залежно від конкретної мови програмування, в програмі здійснюється також опис величин з метою їхнього подальшого використання.
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 33 1.6. Поняття алгоритму. Властивості алгоритмів Протягом тисячоліть люди в повсякденному житті керуються набором правил, що описують послідовність дій, необхідних для досягнення деякого результату. Часто цю систему правил називають алгоритмом. Слово алгоритм походить від прізвища середньовічного узбецького математика Мухамеда ібн Муси аль Хорезмі (IX сторіччя). Він сформулював загальні правила арифметичних обчислень з багатозначними числами. Пізніше в Європі ці прийоми назвали алгоритмами - від латинського написання імені аль Хорезмі. Алгоритм можна трактувати як чітке, зрозуміле і докладне розпорядження, на підставі якого виконавець (машина чи людина) повинні покроково виконувати певне типове завдання, яке від початкових даних приводить до шуканого результату або до повідомлення про неможливість його отримати. Для розв’язання одній і тієї ж задачі на ПК, зазвичай, існує багато алгоритмів. Обрати необхідно той, який вимагатиме мінімальних затрат комп’ютерної пам’яті і часу для одержання результату. Необхідно розрізняти поведінку людини, якій доручено обчислення, і роботу обчислювальної машини. Постановка задачі для машини відрізняється від постановки задачі для людини тим, що у випадку машини усе необхідно передбачити заздалегідь. Виконання інструкцій відбувається всередині машини без втручання людини. Обчислювальна машина не може прийняти вірне рішення, якщо у ній не закладено правильних докладних інструкцій. Завжди варто пам’ятати, що машина не може мислити. Вирізняють такі властивості алгоритмів: • дискретність - алгоритм складається із окремих (дискретних) кроків - команд, розпоряджень, чітко відокремлених одна від одної. Тільки після виконання попереднього кроку виконавець зможе розпочати виконання наступного; • скінченність - число цих кроків не безмежне: виконання алгоритму завершується за скінченне число кроків; 2 7-451
34 1.6. Поняття алгоритму. Властивості алгоритмів • зрозумілість - алгоритм, складений для конкретного виконавця, містить тільки ті команди, які належать до системи його команд; • виконуваність - він складається тільки з припустимих команд, які виконавець у стані виконати щодо певних вхідних даних; • однозначність (точність) - це такий опис послідовності команд, який унеможливлює їхнє подвійне тлумачення: кожна команда алгоритму задає однозначну дію виконавця; • результативність - після виконання всіх команд алгоритму одержуємо результат, який може виявитись і неправильним; • ефективність - це здатність отримати результат з мінімальними затратами ресурсів; • масовість (універсальність) - алгоритм придатний для вирішення не одній, а багатьох задач, що належать до певного класу; • елегантність - критерій суб’єктивний, однак надто важливий для програмістів: елегантне розв’язання задачі є водночас простим, оригінальним та оптимальним (під оригінальністю* розв’язку розуміють його неочевид- ність). Щодо кожного алгоритму розрізняють вхідні і вихідні дані. Алгоритм може бути і помилковим. Тоді програма, розроблена за цим алгоритмом, може самостійно не завершитись ніколи (зациклитись) або видати неправильний результат. Така ситуація можлива, якщо в алгоритмі є логічні помилки, або для розв’язання задачі вибрано неправильний метод. 1.7. Форми представлення алгоритму Існує декілька форм задавання алгоритму: • описова словесно-формульна; • псевдокод або спеціальна алгоритмічна мова; • графічна форма (діаграми Нессі-Шнейдермана);
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 35 • графічна форма (блок-схеми) - послідовність геометричних фігур-блоків: кожен блок графічно відображає функції визначеної ділянки алгоритму; • програма, написана певною мовою програмування. Описовий алгоритм - алгоритм, складений природною людською мовою з використанням математичної символіки. На цьому етапі створюється варіант опису поставленої задачі, що оптимально задовольняє пред’явлені вимоги. Цю роботу виконує математик. Псевдокод та діаграми Нессі-Шнейдермана сьогодні практично не застосовують, отож, ми їх не розглядатимемо. Графічний алгоритм - компактна і наочна форма запису алгоритму (спеціальні графічні знаки із позначенням зв’язків між ними). Графічне зображення алгоритму називають блок-схемою. Із переліченого вище набору способів запису комп’ютерних алгоритмів ми, окрім описової форми подання алгоритмів, у подальших розділах найчастіше використовуватимемо власне блок- схеми - традиційний, наочний і поширений у програмістській практиці підхід. До символіки блок-схем, порівняно із загальновідомими стандартами, у підручнику введено незначні зміни, які полегшують як розуміння алгоритму, так і його майбутнє кодування мовою програмування високого рівня. Нижче наведено опис цієї символіки з відповідним поясненням мовою Разсаі.
36 1.7. Форми представлення алгоритму Графічний символ (ГС) Аналог ТС у програмі Program First; Заголовок головної програми Введіть кількість гармонік Ne Wrltein ('Введіть кількість гармонік Ng'); Readln (Ng) ; Оператор введення даних КОМ = Л • D; S = S + bk*Sin(KOM) + а^Со^КОМ) KOM := k * D ; S : = S + b [k] *S±n (KOM) + a [k] *Cos (KOM) ; Блок операторів присвоєння Gauss (A, b, N, x) ; Оператор виклику процедури If і > Ne then Умовний оператор (розгалуження) Друк результату С Writein (' С =' , С ); Оператор виведення (друку) даних ^ Кінець ^ Завершення програми END.
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 37 Вхід Xe,Ye,Ne,Ngr Xg Yg Вхід х— -16- I Е = G- Т Вихід І Е- Вхідні параметри Procedure <ім'я>(Хе, \e:<munl>;Ne,Ngr:<тип2>; Var Xg Yg:<naml>); Вихідні параметри Рис. 1.1. Позначення процедури Вхідний параметр Function <ім,я>(х:<тип>):<тип функції>; Запис вихідного значення в ім'я функції Ім'я функції Рис. 1.2. Позначення функції На блок-схемах передавання управління позначають стрілкою, якщо передавання спрямоване вгору або ліворуч. Передавання управління вниз і праворуч стрілкою не позначається. Цикли із відомою кількістю повторень ми позначаємо трьома блоками - (1, 3 і 4 (рис. 1.3; 1.4). У цьому випадку знак <— (стрілка вліво) та зменшений розмір блоків 1 і 3 нагадує, що це не блоки арифметичних операторів. Для циклу Бог ... Іо ... </о третій блок містить знак “+” (плюс). Це означає, що параметр циклу А зростає із кроком 1. Відповідно, для циклу ... йоппіо ... </о третій блок містить знак (мінус). Це означає, що параметр і змінюється із кроком -1 (зменшується).
38 1.7. Форми представлення алгоритму к = 1 Г 2 ■ КОМ = k*D S=S+bk *s\n(KOM)+ ak 'qos(KOM) Г 3 ■ - к +1 For k:= 1 to NG do Begin КОМ := к * D ; S := S + b[k]*Sin (КОМ) + a [к] * Cos (КОМ) End; Рис. 1.3. Позначення циклу For to do, Г 1 1 i= Ng , .I—^-i КОМ = і *D S=S+bt*sm(KOM)+ at *cos(KOM) і i - 1 Рис. 1.4. Позначення циклу For... downto .„do, та його програмний аналог Алгоритм можна оформити і як таблицю, графік і т. д. Перелічені форми запису алгоритму об’єднуються однією загальною властивістю - наочністю сприйняття для людини. Отож, їх використовують на першому і другому етапах рішення задачі. На жаль, усі зазначені форми представлення алгоритму недоступні для сприйняття обчислювальній машині. Єдиною формою подання алгоритму на мові, зрозумілій машині, слугує алгоритм як програма, записана мовою програмування. та його програмний аналог For і:= Ng downto 1 do Begin KOM : = і * D; S:=S + b [і] * Sin (KOM) + a[i] * Cos (KOM) End;
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 39 1.8. Порівняння форм запису алгоритму Здебільшого, алгоритм найкраще записувати як програму. Графічний алгоритм доцільно викбристовувати як високорівневий опис складних програм, що містять значну кількість умовних і безумовних переходів, циклів і підпрограм. Якщо при описі алгоритму необхідні особливі пояснення (наприклад, введення і перетворення формул), перевагу надають описовому алгоритму. Важливо пам’ятати, що виконавцем алгоритмів зазвичай слугує не людина, а автомат. Серед усіляких автоматів комп’ютер є лише одним (хоч і вражаючим) прикладом виконавця, чия поведінка реалізується на основі алгоритму. Створення комп’ютерів суттєво вплинуло на розвиток теорії алгоритмів - однієї з галузей математики. Комп'ютер діє як автоматичний формальний виконавець алгоритмів обробки інформації. Це його головна властивість. Людству необхідно розуміти обмеженість можливостей комп’ютера як виконавця, усвідомлювати необхідність самому передбачати всі наслідки команд, що доручаються комп’ютеру для виконання, оскільки усю відповідальність за використання комп’ютерів суспільством покладено тільки на людей. 1.9. Приклад розв’язання квадратного рівняння Умова. Теплохід пройшов за течією річки 48 км і стільки ж - проти течії. Затрачено на весь шлях 5 год. Визначити швидкість теплохода у нерухомій воді, якщо відомо, що швидкість течії становить 4 км/год. Розв'язок: Позначимо швидкість теплохода у стоячій воді через х км/год. Тоді його швидкість за течією річки становитиме (х+4) км/год, а проти течії - (х- 4) км/год. Отож, він пройде за 48 48 течією відстань у 48 км за год, а проти - течії за год. х + 4 х-4 Згідно з умовою задачі одержимо: - — - + - = 5 . Виконуючи алгебричні перетворення, х-4 х+4 одержимо таке квадратне рівняння: 5х2 -96х-80 = 0 . Розв’язуючи його, знайдемо шукану швидкість.
40 1.9. Приклад розв’язання квадратного рівняння Завдання. Подати алгоритм розв’язання квадратного рівняння ах2 +Ьх + с = 0 у трьох варіантах: • словесно-формульному (описовому); • як блок-схему; • як програму мовою Раясаі. Із шкільного курсу алгебри відомо, що це рівняння завжди має два корені. Залежно від значення дискримінанта И = Ь2 -4ас, можливі три випадки: • /) < 0 - обидва корені є комплексними (уявними); _ь • £) = 0 - корені є дійсні і рівні: х = —; 2 а • £> > 0 - обидва корені є дійсні, різні і визначаються за формулами: -ь+4г> -ь-415 х\ = ; х2 = . 1 2 а 2 2 а Описова форма представлення алгоритму Алгоритм розв’язання цієї задачі полягає у виконанні послідовності кроків: 1. Вводимо в пам’ять комп’ютера коефіцієнти рівняння: а, Ь, с . Для цього попередньо забезпечуємо (шляхом відповідного опису) виокремлення компілятором необхідного місця в оперативній пам’яті. Передбачаємо також виокремлення місця для запису дискримінанта рівняння О і змінних х, хі та х2. 2. Якщо водночас а- 0 і Ь = 0 - друкуємо повідомлення: “Рівняння не сумісне” і закінчуємо роботу програми. 3.Якщо а-0, але Ь Ф0, обчислюємо і друкуємо значення єдиного кореня: х =-с ІЬ і закінчуємо рахунок. 4. В іншому випадку обчислюємо дискримінант: О = Ь2 - 4ас . 5. Якщо В < 0 - друкуємо повідомлення: “Дійсних коренів немає” і закінчуємо роботу програми. 6. В іншому випадку обчислюємо значення х = -Ь /(2а). 7. Якщо О = 0, друкуємо повідомлення: “Два корені рівні: х=”, друкуємо значення х і завершуємо роботу програми.
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 41 8. В іншому випадку обчислюємо значення х2 = 'Л5/(2а). Далі послідовно обчислюємо х\ = х2 + х та х2 = х-х2, друкуємо значення коренів х\ і х2 і завершуємо роботу програми. Зауважимо, що цей відомий зі -школи алгоритм може незадовільно працювати у випадку, коли значення Ь2 є значно більшим від значення |4ас|. У цьому випадку один із коренів формуватиметься шляхом віднімання двох близьких чисел, що спричинить втрату точності. Цього можна уникнути, якщо за класичною формулою знайти корінь, обчислення якого не спричинить до втрати точності, а другий корінь обчислити за відомою формулою Вієта. Наприклад, для значень коефіцієнтів: а = 1, Ь = -320, с = 16 точнішими будуть обчислення за такими формулами: —Ь + уі~Г) _ с х і-—^ ; хі - Графічна форма представлення алгоритму Рис. 1.5. Блок-схема алгоритму розв’язування рівняння ах?+Ьх+с=0
42 1.9. Приклад розв’язання квадратного рівняння Програму розв'язання квадратного рівняння мовою Pascal, згідно з алгоритмом, що на рис. 1.5, можна реалізувати так: Program X±o_Kv_rivn; Uses Crt; Var a, b, c, xl, x2, x, D : Real; BEGIN ClrScr; Write{'Введіть коефіцієнти a b c =>'); Readln (a, b, c) ; If a = 0 then If b = 0 then Begin Writeln ('Рівняння не сумісне1); Repeat Until KeyPressed; Halt End else Begin x := - c / b; Writeln (1 Корінь x = *, x:8:2); Repeat Until KeyPressed; Halt End else Begin D := Sqr (b) - 4 * a * c; If D < 0 then Begin Writeln ('Дійсних коренів немає'); Repeat Until KeyPressed; Halt End *else Begin x - b /(2 * a) ; If D = 0 then Begin Writeln ('Два корені рівні: х=',х:8:2); Repeat Until KeyPressed; Halt End; x2 := Sqrt (D) /(2 * a) ; xl := x2 + x; x2 := x - x2; Writeln (' Корені: xl=',xl:8:2 , ' x2=',x2:8:2 ) End End; Repeat Until KeyPressed END.
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 43 1.10. Етапи розробки програмного забезпечення Мета розв’язання будь-якої фізичної задачі - отримання корисних результатів або доведення факту, що такі результати отримати неможливо, оскільки задача не має розв’язку. Результатами можуть слугувати певні числові значення, які представляють інтерес для дослідника, інформація про працездатність деякої системи, факт відповідності вихідних параметрів системи заданим значенням, обчислення набору технологічних показників для виготовлення певного технічного пристрою тощо. Узагальнений алгоритм розв’язання абстрактної задачі наведено на рис. 1.6. Стисло пояснимо кожен функціональний блок. 1. Задачу розпочинають розв’язувати, якщо зроблено її постановку, тобто визначено вхідні дані, конкретизовано очікуваний результат і форму його представлення. 2. Не кожна задача для свого розв’язання вимагає застосування комп’ютера. Іноді можна обійтись ручкою, аркушем паперу і калькулятором. 3. Якщо це можливо, обирають адекватний до задачі метод її розв’язку. 4. “Ручне” розв’язання задачі. 5. Аналіз отриманих результатів, перевірка їхньої правильності і, в разі отримання позитивної відповіді, практичне їхнє використання. 6. Якщо аналіз умови задачі засвідчив, що без комп’ютера її не розв’язати, дослідник намагається підібрати стандартне програмне забезпечення, з допомогою якого можна це зробити. 7. Наявність стандартних програм чи пакетів не означає, що їх негайно можна використати для розв’язання поставленої задачі. Можна назвати щонайменше три причини цього: • пакет потрібно купити, а він може коштувати не дешево, що для розв’язання порівняно простих задач є недозволеною розкішшю; • купівля пакета не означає його негайного успішного застосування (перед початком використання його необхідно освоїти, а це, зазвичай, не просто);
44 1.10. Етапи розробки програмного забезпечення • сучасні програмні системи для розв’язання фізичних задач вимагають для своєї роботи потужних комп’ютерів, оснащених відповідною операційною системою (їхнє придбання спричинює додаткові матеріальні затрати). 8. Якщо все-таки відповідний пакет програм придбано і освоєно, можна починати його використання. Стандартні математичні пакети загального призначення (МаікСай, МаіІаЬ,
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 45 МШетаНса) об’єднують під однією оболонкою класичні чисельні методи. Дослідникові необхідно знати особливості їхнього ’.тстосування і побудови на їхній базі відповідного алгоритму для розв’язання його конкретної задачі. Існують надзвичайно потужні вузькоспеціалізовані програмні комплекси, проте вони надто дорогі та складні. 9. Щоб розробити власні програмні засоби для розв’язання потрібного класу задач, необхідно володіти фахом програміста, мати доступ до комп’ютера з встановленим на ньому відповідним середовищем програмування. Розробку необхідної системи можна, звичайно, замовити відповідному колективу програмістів, однак цей процес, зазвичай, дорогий і довготривалий. 10. Якщо прийнято рішення щодо самостійної розробки програмного забезпечення, то до початку його розробки доцільно мати чітке уявлення, якого класу програмний продукт розроблятиметься: чи це буде програма для одноразового розв’язання однієї задачі, чи програмне забезпечення для тривалого розв’язання цілого класу споріднених задач. Від цього залежить як інтерфейс програми, так і рівень забезпечення її робастності (стійкості). Розробку універсальної системи здійснює, зазвичай, колектив програмістів, дії яких вимагають чіткого узгодження і синхронізації. 11. Кожна фізична задача щодо її комп’ютерного розв’язання вимагає вибору відповідного математичного забезпечення у вигляді набору чисельних методів. 12. Перед початком програмування слід детально і всебічно обдумати кожен крок алгоритму розв’язання задачі. Недостатня увага до цього етапу збільшує імовірність піти хибним шляхом, що в майбутньому спричинить значні затрати на переробку і виправлення алгоритму. Хороше правило програмування - завжди очікувати найгіршого. Отож, до початку кодування алгоритму на мові програмування його необхідно максимально продумати. Розроблений алгоритм записують однією із словесних чи графічних форм його представлення. Цей крок є складовою частиною документування програми. Він мало пов’язаний із конкретною мовою програмування. 13. Зазвичай, більшу частину програмного забезпечення створюють мовами програмування високого рівня. Для фізичних і науково-технічних задач подібними мовами є Раясаі, Рогігап або Сі.
46 1.10. Етапи розробки програмного забезпечення Якщо процес розв’язання задачі вимагає максимальної швидкодії чи використання специфічного апаратного забезпечення, окремі, найкритичніші фрагменти програми пишуть на Асемблері. Для виокремлення таких фрагментів розроблено спеціальні програми- профілювальники. 14. Написання програми - це переклад формалізованих частин алгоритму на конкретну мову програмування. Цей етап доцільно робити на папері із використанням олівця та гумки. Паралельно із написанням програми необхідно вставляти в її текст коментарі (пояснення). Остання вимога є обов’язковою, якщо програма не є цілком примітивною і в майбутньому передбачено її модернізацію. 15. Написану і прокоментовану програму вводять з клавіатури у файл. Після завершення цього процесу розпочинається етап виправлення синтаксичних помилок і перший запуск програми на виконання. Працездатність розробленої програми досліджують шляхом її тестування на основі простих задач окремої предметної області, розв’язок яких є відомим. Добре продумана система тестів дає змогу виявити і виправити значну кількість логічних помилок алгоритму. На жаль, виправлення всіх помилок досягають тільки після розв’язання програмою безлічі реальних задач, тобто уже в процесі її експлуатації. 16. Кожна програма покликана видавати результати своєї' роботи у наглядній і зручній для сприйняття користувачем формі (табличній, текстовій, графічній) чи записувати їх у файл на диску для подальшого автоматизованого опрацювання. 17. У випадку розробки універсального програмного комплексу на перший план виходять проблеми, які у попередніх пунктах не стоять настільки гостро: • Складну систему програм написати одна людина не в змозі. Це робота для колективу програмістів, який працює як єдине ціле. • Окрім ефективних алгоритмів обробки даних необхідна детальна розробка програмного інтерфейсу - дружнього, інтуїтивно зрозумілого, який контролюватиме кожен крок процесу введення даних. • Необхідна команда кваліфікованих тестерів, які здійснюватимуть комплексну перевірку працездатності та ефективності роботи всієї системи (у компанії МісгоЗо/?, наприклад, до кожного розробника прикріплений його
1. ПРОГРАМУВАННЯ ІНФОРМАТИКА, АЛГОРИТМИ 47 персональний тестер для здійснення проміжного тестування перед об’єднанням зміненого коду із базовим кодом проекту). • Початкова стадія експлуатації системи виявляє безліч проблем, які ні замовник, ні розробники не передбачили на етапі проектування (ці проблеми доводиться усувати розробникам). У процесі використання системи доводиться її модернізовувати та видозмінювати. Цей етап називають супроводом системи. Дослідження особливостей усіх цих аспектів програмування виходить за рамки нашого курсу і детальніше вивчається у програмній інженерії (Software engineering). 1.11• Вимоги до програмування Талант створювати неможливо, проте можна створювати культуру, тобто ґрунт, на якому таланти ростуть і процвітають. Чим більшою, ширшою і демократичнішою є культура, тим частіше з’являються таланти і генії. Один вчений назвав живопис Ренесансу епідемією геніальності. Нейгауз Г. Про мистецтво фортеп’янної гри. 1958 р. Світ комп’ютерів щоденно змінюється з темпом, який постійно зростає. Програміст змушений безперервно оволодівати новими знаннями, новими мовами програмування, новими технологічними підходами та ідеями, які вимагають цілковитого перегляду понять, які раніше здавались непорушними. Програми стають громіздкими, об’єднуються у системи, пакети, комплекси, їхні інтерфейси постійно ускладнюються, а терміни виконання робіт скорочуються. У цій ситуації дуже важливо визначити певні фундаментальні незмінні ідеї, які створювались в результаті багатолітньої практики, усвідомити їхнє значення і використовувати їх у роботі. На жаль, такі життєво важливі поняття, як тестування, налагодження, хороший стиль, оптимальність програм вивчаються програмістами не в навчальному закладі, а на практиці, ціною величезних затрат власного часу і нервів. Проте всім відомо, що найкраще вчитись на чужих помилках. “Людина вчиться писати, читаючи. Мабуть причиною того, що ми не вчимось програмувати, читаючи чужі програми - є те, що
48 1.11. Вимоги до програмування ці програми написані поганим стилем і тому не є наочними. Існування подібних програм є підтвердженням того, що автор у ній сам до кінця не розібрався. Такі програми - це чорна скринька, про яку відомо, що вона робить із вхідними даними, але не відомо, як вона це робить” [17]. Існують загальні концепції написання програм, які не повинні залежати ні від особливостей конкретної мови програмування, ні від можливостей операційної системи, ні від конкретного завдання. Знання цих концепцій дає змогу програмістам працювати ефективніше та професійніше. Сформулюємо головні правила і принципи написання “хороших” програм: • простота - програма має бути короткою і керованою; • ясність - програма повинна бути зрозумілою як машині, так і людині; • універсальність - програма коректно працює в широкому діапазоні ситуацій. Простота і ясність є першими і найважливішими серед цих основ, оскільки все інше так чи інакше з них випливає. Необхідно намагатись робити все якнайпростіше: обирати найпростіший алгоритм, найпростішу структуру даних, яка даватиме змогу розв’язати поставлену задачу; програмувати простими і зрозумілими операторами. Не потрібно ускладнювати нічого доти, доки в цьому не виникне гострої необхідності (наприклад, доки заміри швидкодії 4 нашого програмного модуля не покажуть незадовільних результатів). Зусилля, які ми затратимо для того, щоб зробити програму наочною і зручною для читання, зазвичай, є значно меншими, ніж майбутні затрати часу на виправлення помилок і переробку погано написаної програми. Програмісти- практики категорично радять дотримуватись американського принципу KISS'. “Keep It Simple, Stupid)” (Роби якнайпростіше, дурню!) Універсальність часто йде поруч з простотою, оскільки вона передбачає розв’язок проблеми один раз у загальному вигляді, а не повернення до неї у кожному специфічному випадку. Іноді такий підхід дає змогу легше розв’язати проблему портування: доцільніше знайти одне загальне рішення, яке працюватиме в усіх системах програмування, ніж аналізувати розбіжності кожної системи. Програми мають тенденцію жити довше і виконувати
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 49 більше функцій, ніж автори планують на початку їхньої розробки. Немає нічого більш постійного, ніж тимчасове. Інтерфейси є одним із важливих*моментів у програмуванні. Інтерфейс описує правила взаємодії*'різних частин програми, або програмного комплексу, а також взаємодії між користувачем і програмою. Аспекти, зв’язані з ними, проявляються в багатьох місцях. Найочевиднішим прикладом є взаємозв’язок програми з бібліотеками. Існують також інтерфейси між різними програмами, а також між користувачами і програмами. У проектуванні інтерфейсів ідеї простоти та універсальності мають особливе значення. Інтерфейси необхідно проектувати вкрай детально. Робити їх якомога лаконічнішими, доки не стане цілком очевидно, що переваги від нововведень перевершують недоліки додаткового ускладнення. Вони повинні бути настільки послідовними та очевидними, щоб їх можна було легко опанувати і використати. Інтерфейси повинні приховувати від користувача деталі реалізації алгоритму, а не його можливості. Подібні між собою речі необхідно робити однаковими. Тоді безліч моментів стануть інтуїтивно зрозумілими. Еволюційність. Практично неможливо написати довершену програму з першої спроби. Глибоке і всебічне осмислення проблеми відбувається тільки на основі поєднання теоретичних роздумів та узагальнення досвіду, який приходить під час дослідної експлуатації початкового варіанта програми. Незамінною є зворотна реакція користувачів. Сформулюємо цикл розвитку програмної системи: • створення експериментального варіанта програми; • експерименти з цим варіантом; • зворотний зв’язок з користувачем; • подальше удосконалення.
50 1.12. Стиль програмування 1.12. Стиль програмування Чим кращий у програміста стиль, тим легше читаються його програми. Культура і дисципліна у написанні програм запобігає виникненню у них значної кількості помилок. Навчаючись програмувати, необхідно із самого початку намагатись виробити собі хороший стиль програмування, а не розраховувати, що це прийде з часом. Хороший стиль це: • очевидна логіка і зв’язність програми; • природні математичні вирази; • смислові імена всіх елементів програми; • акуратне та одноманітне форматування рядків програми; • розгорнуті і зрозумілі коментарі; • відсутність хитрих трюків і незвичних конструкцій; • жорстке дотримання Coding Conventions - правил програмування, заведених на проекті; • дотримування принципу оптимального використання і своєчасного звільнення ресурсів машини. Зазначимо головні аспекти правил програмування, які використано далі. Ім'я змінної або підпрограми повинно містити певну інформацію щодо призначення окремого елемента. Критерії його оцінювання - інформативність, лаконічність, зручність вимовляння. Глобальним змінним бажано присвоювати довші імена з метою їхньої більшої інформативності щодо призначення певного елемента. Доцільно опис кожної глобальної змінної супроводжувати коментарем щодо її призначення та ролі у програмі. При використанні довгого імені, що складається з двох чи більше слів, доцільно кожне з цих слів записувати з великої літери, розділяючи слова символом (нижнє підкреслення). Наприклад'. Rozmir_Masyvu . Ім’я локальної змінної, використане всередині короткої підпрограми, доцільно обирати коротким. Його призначення легко
і. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 51 »розуміти з контексту. Ще з часів перших версій мови Fortran йикористовують змінні ij, A, Z,, М, N для позначення цілих чисел, S • для зберігання суми, R - для зберігання проміжного (робочого) значення змінних і т. д. Природним є* використання імен /, у, А як імінних циклу, а М, N — для зберігання розмірів масивів. Під повідно, Р, Q - для позначення вказівників, F - для файлових імінних. Чим більший розмір програми, тим сильніше зростає роль систематизації імен. Дотримання цих правил допомагає легшому розумінню як власних програм, написаних раніше, так і чужих, оскільки їх доводиться читати при модернізації програм і при вивченні чужого досвіду. Подібним елементам програми варто надавати подібні імена, які б водночас підкреслювали як подібність, так і відмінність цих елементів програми. Вирази необхідно писати так, щоб їхній зміст був максимально зрозумілим, а вираз - зручним для прочитання. Програма повинна бути якомога простішою, а не хитромудрою. Цього досягають правильними відступами - вставкою певної кількості інтервалів всередині операторів і відповідної їхньої кількості на початку рядка. Цим простим прийомом можна значно унаочнити структуру програми. З метою підвищення зрозумілості ииразу доцільно також використовувати додаткові дужки та інтервали між операторами. Складний вираз необхідно розділити на декілька простих. Умовні (логічні) вирази потрібно записувати у такій формі, у якій їх найкраще вимовляти вголос. Наявність у виразах знаків заперечення погіршує сприйняття самого виразу. Часто для підкреслення змістового групування операторів чи операцій використовують дужки (навіть у випадку, якщо, з погляду граматики, ці дужки є зайвими, але полегшують розуміння певного фрагмента програми). Якщо програма буде трохи довшою, проте значно зрозумілішою, це необхідно робити обов’язково. Доцільно вирівнювати по вертикалі відповідні оператори If else у вкладеному логічному виразі. В операторі Case краще використовувати символьні імена, а не цифри. Вибір стане нагляднішим.
52 1.12. Стиль програмування Найважливішою умовою є одноманітність стилю як протягом усього процесу написання однієї програми, так і впродовж усієї практики програмування різних задач. Фахівці радять: при доробці чужої програми з чітко вираженим стилем, який відрізняється від Вашого, не варто переформатовувати програму на свій лад. Адже Ваш стиль навряд чи буде загальновизнаним. Часто у програмі використовують константи, числове значення яких важко зрозуміти. Наприклад, при побудові графіка ми використовуємо константу L = 50;. Без додаткових пояснень важко зрозуміти, що це ширина в пікселях уявної рамки навколо графіка для виведення текстових підписів. Зрозумілішим буде ім’я цієї константи Border_Width. Коментарі - це пояснення оператора чи фрагмента програми. Найлегше зрозуміти алгоритм, реалізований певною програмою, якщо її добре оформлено коментарями. Коментарі у майбутньому можуть стати основою для документації, яку доведеться виготовляти після завершення розробки програми для передачі її замовнику. Коментар не покликаний пояснювати очевидні речі. Не варто пояснювати, наприклад, роботу оператора: і := ± + і; Кожному і так зрозуміло, що він збільшує на 1 значення змінної і. Коментар 'містить інформацію, яку важко виокремити з фрагмента програми. Отож, її доцільно помістити на початку цього фрагмента як пояснення його роботи. Важливо навчитись писати Self Descriptive Code - код, який сам себе пояснює і не потребує коментування. Необхідно, щоб кожна процедура чи функція перед своїм заголовком містила опис функціонала, який вона забезпечує. Необхідно коментувати призначення процедур і функцій, пояснювати роль глобальних змінних і констант, а також зміст полів у записах та об’єктах. У випадку високої складності алгоритму можна прокоментувати його з допомогою посилання на книгу чи статтю, у якій цей алгоритм детально описано. Інколи спроба пояснити заплутаний фрагмент програми стимулює його спрощення або взагалі нову його реалізацію. Найгіршим випадком є коментар, що не відповідає певному фрагментові програми. Це може трапитись, якщо у прокоментовану
1. ПРОГРАМУВАННЯ, ІНФОРМАТИКА, АЛГОРИТМИ 53 програму внесено зміни, а зміни в коментар внесено не було. Такі ситуації є неприпустимими. Коментарі покликані допомагати читачеві програми зрозуміти її роботу, а не вносити додаткової плутанини. Не варто перенасичувати програму коментарями. Коментувати доцільно лише ті частини коду, зміст яких зрозуміти важко. Чим ясніше написано програму, тим менше необхідно коментарів. Не варто коментуватй незграбно написаний фрагмент програми. Необхідно змусити себе переписати цей фрагмент. Коментована неправильно частина тексту програми є неприйнятною. Під час подальшої підтримки коментована частина не обновляється. Згодом намагання скористатись прокоментованим кодом спричинює виникнення великої кількості проблем, які важко виявити і виправити. З метою забезпечення збереження коду при внесенні змін використовують версійність - зберігання працюючого коду в окремому місці станом на певну дату для того, щоб у будь-який момент можна було повернутись до попереднього варіанта. Отже, хороший стиль програмування передбачає використання інформативних імен, логічно побудованих виразів, поліпшення читабельності програми шляхом форматування її рядків, а також наявність коротких і змістовних коментарів. Не варто заспокоювати себе, що всю цю красу можна навести згодом, коли програма запрацює. Є велика ймовірність того, що неохайно написану програму ніколи не вдасться цілковито налагодити і розпочати її використання на практиці. Строгий та одноманітний стиль програмування повинен стати звичкою, тоді він приноситиме чималу користь під час написання нових програм. Продуктивність програми. Будь-яку програму необхідно створювати якнайоптимальнішою. Програми, що розв’язують фізичні задачі, тестують на простих прикладах, на яких їхня мала швидкодія є непомітною. Реальні задачі вимагають значних затрат процесорного часу. Внаслідок цього ще на етапі дослідної експлуатації програм небхідно визначити критичні (з погляду швидкодії) фрагменти програм. З цією метою можна використати заміри часу з допомогою спеціальних програм-профілювальників. У програмах, зазвичай, діє закон 10-90: 10 відсотків програмного
54 1.12. Стиль програмування коду забирають 90 відсотків процесорного часу. Отож, виокремлюючи подібні фрагменти програми, необхідно їх оптимізувати всіма доступними способами, такими як: • поліпшення алгоритму; • максимальна оптимізація структур даних; • удосконалення циклів шляхом попереднього (перед циклом) обчислення значень, які всередині циклу не змінюються; • буферизація операцій введення/виведення; • переписування критичного фрагмента па. Асемблері, • використання обчислень без надлишкової точності. Тестування програм. Тестувати програми необхідно на всіх граничних значеннях даних. Найчастіше виникають помилки, зумовлені похибками, які пов’язані зі скінченою довжиною розрядної сітки процесора або із виходом за наперед визначені межі масивів. Починати тестування необхідно із найпростіших процедур і функцій, закінчуючи найскладнішими. Щодо цього доцільно перевіряти правильність проміжних даних, записаних у файли. Необхідно розробити систему тестів, здатну максимально перевірити взаємодію всіх гілок кожної підпрограми і взаємодію всіх підпрограм, які формують алгоритм роботи системи.
2. МОВА BORLAND PASCAL 2.1. Переваги мови РаБсаІ У середовищі програмістів десятиліттями точиться дискусія щодо того, яку мову програмування вважати кращою. Кожен наводить безліч позитивних нюансів своєї улюбленої мови і не меншу кількість недоліків інших мов. Це як “релігійна” війна, якій немає кінця і в якій відсутні переможці. Наш подальший матеріал базується на мові програмування Разсаі у варіанті її виконання фірмою Вогіапсі. Чому? Головні переваги мови Раясаі полягають у тому, що вона стала мовою, яка дає змогу створювати високоструктуровані програми з низькою імовірністю виникнення логічних помилок. Інколи декларується, що Разсаі розроблено як мову для навчання. До певної міри це правильно. Використання у навчанні - початкова мета її створення. Проте сумнівним є використання у навчанні засобів і формалізмів, які непридатні для розв’язування будь-якої практичної задачі. За нинішніми стандартами Разсаі має очевидні недоліки для програмування великих систем, однак на час його створення він слугував розумним компромісом між бажаним та ефективним. Головними перевагами мови Разсаі можна вважати її гнучкість і надійність, простоту і прозорість конструкцій. Вона цілком відповідає вимогам структурного програмування, оскільки в ній присутній потужний набір структурованих типів даних: масивів, простих записів, записів із варіантами, файлів, множин, а також передбачено створення власних типів даних. Початкове
56 2.1. Переваги мови Pascal вивчення програмування саме на базі цієї мови виховує в людині “правильні навички” програмування. Попередній опис цієї мови опубліковано в 1968 році Ніклаусом Віртом, професором Цюріхського Федерального технологічного інституту (Швейцарія), у “Повідомленнях про Pascal". Вірт є також творцем інших мов програмування, таких як Ejler, Modula, Modula-2, а також співавтором методики покрокової (низхідної) методології розробки програм - найкращої формалізації 70-х років у програмуванні. У 1973 р. побачило світ “Переглянуте повідомлення”, де мову Pascal вже визначено в термінах множини символів Міжнародної організації зі стандартизації (ISO). У повідомленні описано стандарт мови Pascal, який згодом уточнювала Британська робоча група за стандартами (BSWG), Американський Національний інститут стандартів (ANSI) та інші організації. Проте пропоновані уточнення, за змістом, мало зачіпали авторське ‘"Повідомлення про Pascal'. Найпоширеніші версії систем програмування на основі цієї мови для IBM PC-сумісних машин розробила фірма Borland International з 1983 р. Вони мали назву Turbo Pascal з порядковими номерами. Версії з номерами до 4.0 реалізували Стандарт мови Pascal з незначними розширеннями. Четверта версія (1987) внесла істотні зміни в технологію організації модульної структури програм і мала вбудоване інтегроване середовище розробки (Integrated Development Environment - IDE). З версії 5.5 (1989) мову було концептуально розширено, тобто доповнено засобами об ’єктно-орієнтованого програмування. Версію 6. 0 забезпечено об’єктною бібліотекою Turbo Vision, вбудованим Асемблером TASM, вдосконаленими засобами налагодження в рамках нової IDE та іншими доповненнями. Чергові версії мови, зорієнтовані на віконні операційні системи та досконаліші об’єктні бібліотеки, продовжують інтенсивно розвиватися. З урахуванням істотних розширень мови поняття “Стандарт мови Pascal" і сьогодні не втрачає свого значення, оскільки саме Стандарт слугує ядром сучасних версій мови, якщо не брати до уваги долучення до мови засобів об’єктно-орієнтованого програмування. Зазначимо, що для розробки версії мови Object Pascal фірмою Borland наприкінці 80-х років залучали автора мови Я, Вірта. Синтаксичні конструкції, що відповідають термінальному словникові та , лексемам Стандарту мови Pascal, в останніх версіях систем програмування фірми Borland значно розширили. Перший компілятор мови Pascal реалізовано для сім’ї комп’ютерів CDC6000. Його написано мовою Pascal. Проте код, ним генерований, безумовно, поступався коду, генерованому тогочасними компіляторами Fortran'у для відповідних програм. Pascal дає змогу легко здійснити перехід від структурного до об’єктно-орієнтованого програмування. Щодо цього він містить усі необхідні засоби: високу ступінь структурованості, модульність,
2. ШУВКВОШЛМ) РАБСАІ 57 абстрактність і можливість повторного використання як створених програмістом, так і стандартних конструкцій. Безперечно, ця мова за деякими параметрами частково поступається мові Сі, проте складність конструкцій мови Сі вважають її сумнівною перевагою. Для розробки потужного програмного забезпечення, здебільшого, цілком достатньо тих можливостей, які надає у розпорядження програмістові мова Ра5саІ. У ній закладено найважливіші фундаментальні концепції алгоритмів в очевидній, природній формі, легкій для сприйняття людиною. Об’єм конструкцій мови незначний. Усі вони добре продумані і застосовуються не тільки для запису алгоритмів, але й у наукових і науково-популярних статтях для пояснення різних алгоритмічних конструкцій. Отож, на базі стандартної версії мови Разсаі фірмою Вогіапсі розроблено сім’ю Люса/-систем, іменовану ТигЬо Разсаі. До 1992 року розроблено сім версій мови програмування, яка й сьогодні користується широкою популярністю серед масових користувачів і професійних програмістів. Останньою, найпотужнішою версією мови є ВогіапсіРаБсаІ 7.0, яку ми вивчатимемо. Мова налічує зручне багатовіконне інтегроване середовище програмування, швидкий компілятор, налагоджувач, розвинену контекстну допомогу, а також значну кількість прикладів, які спрощують освоєння принципів програмування цією мовою. В середовищі Вогіапй РазсаІ можна створювати різноманітні програми, призначені як для вирішення простих обчислювальних задач, так і для виконання складних розрахунків, таких як обробка результатів фізичного експерименту чи моделювання фізичних процесів і систем. Система Вогіапй Разсаі залишається простою у вивченні, що дає змогу програмістові-початківцю на її основі вивчити методи і способи ефективного програмування. Програми, написані цією мовою, легко налагоджувати і модифікувати. У програміста- початківця формується чітке алгоритмічне мислення, яке дає змогу писати надійні та ефективні програми. Як влучно зауважив ДональдАлкок [3], ліків від любові до мови РаБсаІ ще не знайдено. Фахівці-програмісти не безпідставно вважають, що для початкових кроків у програмуванні мова РазсаІ є найліпшою. Вивчаючи з її допомогою основи програмування, значно легше можна опанувати інші, сучасніші та потужніші мови [61].
58 2.2. Поняття інтегрованого середовища 2.2. Поняття інтегрованого середовища Інтегроване середовище - якісно нове утворення щодо окремо взятої мови. Уточнимо це тепер уже звичне та інтуїтивно зрозуміле поняття. Кожна мова програмування вирізняється описом своїх правил запису коду алгоритму на папері - і тільки. Очевидно, що для реалізації цього коду на комп’ютері необхідні певні засоби. Комплекс таких засобів разом із мовою програмування називають системою програмування. Система програмування (Programming system) - система автоматизації процесу програмування, утворена мовою програмування, компіляторами або інтерпретаторами програм, написаних цією мовою, відповідної документації, а також допоміжними засобами для підготовки програм до виконання. Зазначимо тут два моменти. По-перше, наведене визначення не передбачає об’єднання всіх компонентів в єдиних рамках. Наприклад, редактор для набору текстів програми, компілятор, редактор зв’язків можуть існувати і запускатися як окремі програми, як, власне, і було на початкових етапах програмування. По-друге, йдеться, передусім, про необхідні компоненти, без яких реалізація алгоритму на комп’ютері неможлива; мова високого рівня і система програмування на цій мові нерозривно взаємозв’язані. • Розвиток систем програмування спричинює до розробки інтегрованих програмних середовищ, де враховано ще й інтереси програміста. Інтегроване середовище (Integrated environment) - система програмних засобів, яка містить усі компоненти та необхідні програмісту засоби і забезпечує їхню одноманітність. Це визначення потребує деякого уточнення. Інтегроване середовище програмування - замкнута система програмних засобів, яка дає змогу, не виходячи з неї, вирішити задачу, починаючи з набору тексту програми і завершуючи отриманням результатів. Інтегровані середовища, здебільшого, налічують: • редактори текстів; • програми обробки (транслятори, редактори зв’язків, завантажувачі, налагоджувачі);
2. МОВА BORLAND PASCAL 59 • утиліти (службові програми); • бібліотеки стандартних програм; • засоби створення сервісу (меню, вікон тощо). Процес роботи в середовищі за.формою значно відрізняється від звичного покрокового процесу роботи з програмою. Важливо, що в інтегроване середовище мову програмування зачислено як елемент і, зазвичай, її вже не розглядають незалежно. Незалежні компілятори та редактори зв’язків якщо й існують, то широкого розповсюдження не мають. Отже, з одного боку, є мова зі своїм описом, а з іншого - її можна використати тільки в рамках інтегрованої системи. Яскравим прикладом такого взаємозв’язку є середовище розробки додатків Delphi, де “базовою” мовою програмування є Pascal. Твердження в лапках виділене так не тому, що є помилковим, а тому, що воно є відносно справедливим. Мова Object Pascal, яку використовують в Delphi, володіє новими потужними можливостями (що природно). Це - розширений Pascal, звичним способом описаний, на якому Ви можете записати власну процедуру обробки даних - проте реалізувати її можна тільки в Delphi, оскільки відповідний компілятор є неподільним елементом системи. Інтегровані середовища програмування фірми Borland - це гак звані Тигйо-системи, до яких належить Turbo Pascal, Turbo Сі, Turbo BASIC, Turbo Assembler та ін. Мова Turbo-системи значно відрізняється від стандарту завдяки значній кількості принципово важливих механізмів, без яких мову вже неможливо представити і які давно стали базовими. Отож, порівняння як стандарту мови з версіями мови різних Тигйя-середовищ, так і порівняння старих версій між собою втратило актуальність. Twrüö-середовища ретельно продумані і дуже зручні. Turbo- компілятори відрізняються високою швидкістю компілювання. Існують такі версії Тигія-середовшц мови Pascal. - Turbo Pascal 3.0- доволі примітивне середовище; - версія 4.0- практично не використовувалася. Обидві версії доволі швидко замінили істотно довершенішою версією 5.0. • Починаючи з версії Turbo Pascal 5.5, мова налічує засоби об’єктно-орієнтованого програмування.
60 2.2. Поняття інтегрованого середовища • Для версії Turbo Pascal 6.0 і вище розроблено об’єктно- орієнтовану бібліотеку Turbo Vision, призначену для проектування інтерактивних інтерфейсів користувача. • Borland Pascal 7.0 - нове інтегроване середовище, що налічує дві версії - для роботи під DOS і під Windows. Наступний крок у розвитку і використанні мови Pascal - інтегроване середовище розробки додатків Delphi - зробило непотрібною бібліотеку Turbo Vision. Використано зовсім інші парадигми програмування (візуальне на базі об’єктного), значно ширші цілі, інший рівень програмного забезпечення і технологію розробки програмних продуктів (додатків), а це - предмет іншого курсу. 2.3. Робота в інтегрованому середовищі Borland Pascal Інтегроване середовище Borland Pascal (ВР) належить до сім’ї Тигбо-компіляторів, розроблених фірмою Borland International, Inc. Базові характеристики цих компіляторів: • висока швидкість компілювання; • наявність дружнього та зручного інтерфейсу: для користувача передбачено конфігурування багатовікон- ного середовища; • комфортна система меню; • діалогова система налагодження програм. Компілятори цієї фірми дають змогу працювати в середовищі DOS з програмами багатомодульної та оверлейної структури. З погляду користувача, ВР володіє досконалим редактором текстів, що містить у собі засоби компілювання, редагування та виконання програм, а це значно підвищує ефективність роботи програміста.
2. МОВА BORLAND PASCAL 61 2.3.1. Початок і завершення роботи Виклик середовища ВР можна здійснити шляхом запуску на пиконання файла Вр.ехе, розташованого у директорії ...:\BP\BIN, одним зі способів, передбачених ОС Windows: через Windows Explorer, за посередністю Bat-файла або з оболонки типу Windows Commander чи Volkov Commander. Після успішного запуску середовища отримаємо вікно, зовнішній вигляд якого подано на рис. 2.1. Верхній рядок екрана містить назву версії компілятора. Ііижче розташовано рядок головного текстового меню. Під ним - вікно екранного редактора для набору та редагування тексту програми. Внизу бачимо список “гарячих клавіш”, доступних у иоточний момент часу. <% jrAQi і вІ*1 — NONflMEOÜ.PAS — =1 = [ І ]=n 1:1 Fi Help F2 Saue F3 Open AlnF9 Compile РЭ Make ftlt«Fl0 Local menu A Рис. 2.1. Вигляд вікна після запуску ВР.ехе на виконання Залежно від ситуації, на головному екрані можуть з’являтися інші вікна (наприклад, вікно допомоги, компілювання або результатів роботи програми). У вікні редактора можна створювати і налагоджувати програми, формувати текстові файли вхідних даних тощо. Виконання будь-якої команди нижнього рядка екрана можна активізувати лівою клавішею миші чи натисканням відповідних “гарячих клавіш”, перелік яких подано нижче: FI - (Help) показати довідку; F2 - (Save) записати файл з вікна редактора на диск; F3 - (Open) прочитати файл з диска у вікно редактора;
62 2.3. Робота в інтегрованому середовищі F4 - (Run\Go to cursor) виконати фрагмент програми до курсора; F5 - розкрити вікно на весь екран або повернути йому попередні розміри; F6 - активізувати наступне вікно; F7- (Run\Trace into) трасувати процедуру або функцію; F8 - (Run\Step over) трасувати програму, пропускаючи підпрограми; - (СотріІе\Маке) компілювати програму; Що 10 - перейти в головне (текстове) меню; 'trl+Fl - одержати контекстну довідку; Ztrl+F2 - зняти режим налагодження; 7ґ/7+КЗ| - активізувати вікно програмного стека; - феЬ^\ЕгаІиаіе\Мо<1і/у) обчислити вираз або показати/змінити змінну; СігІ+Р5 - перейти до режиму установки положення і розмірів вікна; Ctrl+F7 - (.Debug\Add watch) додати вираз у вікно налагодження^ - перемкнути контрольну точку; - (СотріЩСотріїе) виконати компілювання і запуск Ctrl+F8 Ctrl+F9 програми; \Ctrl+Del - очистити буфер редактора; \Ctrl+In^ - копіювати блок у буфер редактора. Для виходу із системи достатньо натиснути клавіші Alt +Л|. Примітка: Знак “+” (плюс) означає, що ми спочатку натискаємо клавішу j/Щ а потім, не відпускаючи її, натискаємо jxj. 2.3.2. Вікна системи Вікно - це екран або його частина, де розташовано певну інформацію. Середовище ВР містить декілька типів вікон: • вікно редактора; • діалогові вікна; • вікна повідомлень. Наприклад, одне з вікон повідомлень містить інформацію щодо результатів процесу компілювання. Під час розробки
2. МОВА BORLAND PASCAL 63 програми, здебільшого, використовують вікно редактора Edit (рис. 2.2), вікно перегляду Watches (рис. 2.3) та екран користувача - пікно Output (рис. 2.4). Водночас на екрані можна розташувати декілька вікон. Вікно може перебувати в одному із двох статусів - активному чи пасивному. У кожен момент часу активним може бути тільки одне вікно. Активне вікно має подвійні лінії рамки. Якщо вікна перекриваються, активне вікно завжди розташоване поверх інших. Розміри вікон можна змінювати з допомогою кута зміни розміру. Вікна можна переміщати екраном, закривати їх і відкривати. Значна частина вікон налічує такі елементи (рис. 2.2): • рядок заголовка вікна; • маркер закриття (згортання) вікна (у лівому верхньому куті); • номер вікна (від 1-го до 9-ти, на верхній рамці вікна праворуч). Рис. 2.2. Елементи вікна редактора (Edit) системи ВР Рис. 2.3. Вікно перегляду (Watches)
64 2.3. Робота в інтегрованому середовищі Рис. 2.4. Екран користувача (Output) з результатами Є ще спеціальні типи вікон - діалогові (рис. 2.5). Ці вікна не можна розкрити на весь екран. Вони можуть налічувати органи керування: радіокнопки (маленькі квадратні або круглі віконця) для задавання режимів роботи, кнопки заданої дії, вікна введення рядка і вікна зі списками. Кнопки у вікнах представлені їхніми зображеннями з написом на кнопці. Кнопку можна активізувати підвести до неї курсор і натиснути ліву клавішу миші, або вибрати кнопку за допомогою клавіші Tab і натиснути клавішу Enter Jj. І Display swapping * : .^.||Мі • . . ■ Рис. 2.5. Приклади діалогових вікон Здебільшого, вікна діалогу мають три стандартні кнопки: ОК - для виконання обраної дії; Cancel - для скасування обраної дії; Help - для виклику допомоги. Вікно редагування має в лівій частині нижньої рамки номер рядка і стовпця, у яких розташований курсор. На рис. 2.2 - це 1:2. Якщо текст у вікні модифіковано, ліворуч від номера рядка і стовпця розташована * (зірочка). СКЗ Integrated debttigrafing/bi'owsin^
2. МОВА BORLAND PASCAL 65 Рядок заголовка вікна містить його найменування. Рядок заголовка вікна редактора - ім’я файла, розташованого у вікні. Перші 9 відкритих вікон містять у правому верхньому куті свій номер. Для активізації вікна можна натиснути клавішу Аіі+цифра. Цифра відповідає номеру необхідного вікна. Активізувати вікно можна також натисканням лівої клавіші миші, коли курсор встановлено на будь-якому місці видимої частини вікна. Розгортання вікна на весь екран і згортання його до попереднього розміру здійснюють натисканням клавіші миші, курсор якої встановлено на маркер розгортання вікна. Ці дії можна також виконати клавішею /'З, або подвійним натиском лівої клавіші миші, якщо її курсор попередньо поставити на верхню рамку заголовка вікна. Закрити активне вікно можна командою \ilt+F3 . Для переміщення вікна необхідно “перетягнути” його, установивши курсор миші на верхній рамці вікна, або виконати команду Ctrl+F5. Потім перемістити вікно за допомогою “стрілок” - клавіш керування положенням курсора і, після завершення переміщення вікна, натиснути клавішу Enter\ Зміну розміру вікна здійснюють переміщенням його правого нижнього кута курсором миші при натисну тій її лівій клавіші. Без миші можна змінити розмір вікна за допомогою команди \Ctrl+F5 Потім натиснути клавішу \Shifq і, не відпускаючи її, змінити розмір вікна за допомогою “стрілок”. Потім натиснути Enter\ Корисно також пам’ятати такі комбінації клавіш: 1/М-ОІ - одержати список відкритих вікон; 1 lt+Fl Shift+Fl - одержати контекстну довідку; - одержати список посилань довідкової служби; ЧМА+Рщ - активізувати попереднє активне вікно. Смуги прокручування використовують для перегляду вмісту вікна за допомогою миші. Це здійснюють за допомогою ліфта - маркера положення курсора щодо початку і кінця тексту. Для прокручування на один рядок (підняття чи опускання тексту на екрані) необхідно підвести курсор до стрілки в нижній чи верхній частині смуги прокручування і натиснути ліву клавішу миші. Для безупинного прокручування необхідно тримати кнопку натисну- Я 7.461
66 2.3. Робота в інтегрованому середовищі тою. Для прокручування в одну сторінку курсор миші встановлюють на смузі прокручування вище (для прокручування на сторінку вгору) чи нижче (для прокручування вниз) ліфта і натискають ліву клавішу миші. Із середовища ВР командою |4//+F5| можна активізувати екран користувача Output - вікно з виведеними результатами обчислень (рис. 2.4). Повернення в екран середовища здійснюють натисканням клавіші ІEsĄ . 2.3.3. Допомога (HELP) Середовище ВР має розвинуту систему допомоги і підказок HELP. Під час роботи в середовищі у будь-який момент можна активізувати спеціальне вікно з довідковою інформацією, що контекстно взаємозв’язана з поточною ситуацією. Натискання Fl_ з будь-якого вікна дає виклик підсистеми HELP з видачею інформації, що відповідає поточному положенню курсора. Наприклад, з “порожнього” місця у кожному з головних натискання клавіші F1 вікон активізує інформацію про вікно, з якого здійснено виклик допомоги. Повторне натискання |^7| активізує увесь опис системи допомоги. У процесі редагування текстів мови Разсаі можна одержати підказку з правилами написання відповідного оператора мови. З цією метою підводять курсор під ключове слово оператора, щодо якого потрібна підказка, і вводять команду \Ctrl-\rFl . Викликати допомогу можна також введенням команди о/+М. Шп+п\ чи \ilt-\-Fl\ з “порожнього” місця екрана. Одержимо вікно з назвою Turbo Help Index, яке містить список ключових слів розташованих за абеткою, щодо яких можна одержати підказку. Це ж відбуватиметься, якщо натиснути курсором на ключовому слові Help, коли воно присутнє в рядку стану, чи на клавіші діалогового вікна. З метою одержання інформації щодо помилки, повідомлення про яку отримано під час компілювання чи виконання програми, необхідно під час повідомлення щодо помилки натиснути клавішу F1. Зняти підказку чи повідомлення щодо помилки можна за допомогою Esc .
2. МОВА BORLAND PASCAL 67 Ідентифікація файлів. Програми і дані, які створюються та обробляються середовищем ВР, зберігають на диску у файлах. Це можуть бути: 1) тексти вихідних модулів - програм мовою Вогіапй Раясаі, 2) відкомпільовані та готові до виконання програми; 3) вхідні дані і результати роботи програми. Кожен фізичний файл повинен мати своє, притаманне лишень йому ім’я і розширення. У ВР допускаються будь-які розширення, проте є фіксований (стандартний) набір розширень, перелік яких міститься в табл. 2.1: Таблиця 2.1 Основні розширення файлів середовища ВР Розширення Призначення файла *.pas Текст програми мовою Вогіаші Раясаі *.bak Попередня (резервна) версія файла *.ехе Готова до виконання програма *.tpu Модуль {\JNIT) \tpl Файл бібліотеки середовища ВР 2.3.4. Команди екранного редактора Усі команди редактора ВР поділяють на команди переміщення курсора, команди вилучення/вставляння, команди роботи з блоками та ін. Під час їхнього опису використовують такі позначення клавіш управління курсором (стрілок): р—1 - курсор ліворуч; ^ - курсор праворуч; Щ - курсор вгору; Щ - курсор вниз. Команди переміщення курсора CfrfaiSj Ctrl+D Ctrl+A Ш+F Ctrl+E Ctrl+X - на символ ліворуч; - на символ праворуч; або Ctrl+ або або |£ Ctrl+ або Ctrl+Z - на слово ліворуч; - на слово праворуч; - на рядок вгору; - на рядок вниз; Сігі+Щ - прокручування вниз на рядок разом з курсором; - прокручування вгору разом з курсором; С//7+І? або РаяеІІ^ - на сторінку вгору;
68 2.3. Робота в інтегрованому середовищі Ctrl+C\ або PageDn Ctrl+Q »S| або Home Ctrl+Q D Ctri+QJL Ctrl-42 X Ctrl+Q R Ctrl+Q С Ctrl+QIi Ctrl+Q К Ctrl+Q P - на сторінку вниз; - на початок рядка; - в кінець рядка; 'ігІ+Ноте| - на початок екрана; ЧгІ+ЕпЛ - в кінець екрана; - на початок файла; - в кінець файла; 'trl+PageUp або I Ctrl+PageDn на початок блока; - в кінець блока; - на останню позицію (використовують після пошуку/заміни)^^ Сігі+й Щ - на останню помилку. Команди вилучення/вставляння Ctrl+V Ctrl+N Ctrl+Y Ctrl+H Ctrl+G Ctrl+I або \nsert| - активізувати/зняти режим вставляння; - вставити рядок; - видалити рядок; або Васк$рас<\ - стерти символ ліворуч від курсора; або Реіеіе| -1 стерти символ над курсором; - стерти слово праворуч від курсора; СігЩІ її - стерти залишок рядка праворуч від курсора. ,Команди роботи з блоками Під час підготовки текстів програм часто необхідно перенести фрагмент тексту в інше місце або видалити його. Щодо таких операцій зручно використовувати блоки - фрагменти тексту, які розглядають як єдине ціле. Довжина блока буває доволі великою (до 64Кб), він може займати декілька екранних сторінок. У будь- який момент в одному вікні екранного редактора можна позначити тільки один блок. Обмін блоками між вікнами можливий тільки через буфер редактора (див. опцію EDIT у головному меню). Комбінації клавіш для роботи з блоками наведено нижче. k:tri+KB - позначити початок блока; \Ctrl+KK - позначити кінець блока;
2. МОВА BORLAND PASCAL 69 Сігі+К Т - позначити як блок слово, що розташоване ліворуч від курсора; Угі+К Я - надрукувати блок; Угі+К С| - копіювати блок, починаючи з позиції курсора; Угі+К И - перемістити блок; )СігІ+К Н - прибрати виділення блока кольором (повторне використання СіїІ+К Н знову виділить блок); Сігі+К Г| - стерти блок; Сігі+К і? - читати блок з дискового файла; Сігі+К Щ - записати блок на диск; СігІ+КІІ - змістити блок праворуч; СМ+К - змістити блок ліворуч; Уй//?+1?е<І - перенести блок з вікна редактора в буфер; УЛі/?+//і5І - копіювати буфер у вікно редактора. Інші команди І ігі+й ґ - шукати за зразком; їгі+і\ - продовжити пошук; ICtrl+OA - шукати за зразком і замінювати; - припинити подальше виконання пошуку або пошуку/заміни; Сігі+Кп\ - встановити маркер; п=0..9 (див. нижче); Сігі+О п\ - шукати маркер; ог/+ё ц\ - шукати помилку; СігІ+{2 /І - шукати праву парну дужку (див. нижче); Сігі+д)І - шукати ліву парну дужку (див. нижче); Ctrl+Q L Ctrl+Q 7 Ctrl-Ю F - відновити зіпсований рядок (див. нижче); або Сігі+О 7| - увімкнути/вимкнути табулювання; - перемкнути заповнення табулювання; Сігі+О 7| або С/г/+^ 7| - увімкнути/вимкнути автовідступ; Сігі+О 0\ - вставити налаштування компілятора у початок файла (див. нижче). Призначення значної кількості команд зрозуміле без будь- яких коментарів, однак деякі доцільно пояснити додатково.
70 2.3. Робота в інтегрованому середовищі Сігі+К п встановлює в поточну позицію курсора маркер з номером п = 0..9. Маркер на екрані невидимий і ніяк не впливає на виконання програми. Команду використовують спільно з командою Ctrl+Q п\ (шукати маркер з номером п) для прискорення пошуку необхідних фрагментів тексту при розробці великих програм. Зауважимо, що комбінації клавіш Сігі+К п\ набираються так: спочатку натискають клавішу |С/г/|, потім, не відпускаючи її, К\ після цього всі клавіші відпускають і натискають клавішу з цифрою п. Так само набирають команду \Ctrl+Q п Ctrl+Q 1| і \Ctrl+Q fl. Ці команди використовують для пошуку найближчої парної дужки. Команди дають змогу знаходити пари дужок (),{}>[]• Підведіть курсор так, щоб він указував на одну з дужок, і дайте відповідну команду - редактор відшукає відповідну парну дужку. СігІ+О О Ця команда спричинить запис у початок тексту програми рядка, що містить поточні параметри середовища у вигляді директив компілятора, наприклад: { $А+, В- ,Б+ ,Е+ ,Е+1 (3+ , 1+, Іі+ /N4*, 0— , в+, У+ /Х+) {$М 16384,0,655360} ($DEFINE single}. 2.3.5. Система меню середовища ВР З метою спрощення роботи в середовищі ВР використовують певні клавіші та їхні сполучення: • * функціональні клавіші F1 - ІР70І; • клавіша вибору [4й| (Alternative); • клавіша керування \Ctr/j - (ConTRoL); • тимчасова зміна регістра н Клавіші [4Л|, Ctrl і Shift у складених командах використовують у такий спосіб: спочатку’ натискають на одну з них і, не відпускаючи її, натискають додаткову клавішу (наприклад, функціональну чи алфавітну). Таке об’єднання двох клавіш позначають плюсом або пробілом. Наприклад: Alt+F31, Alt+X,
2. МОВА BORLAND PASCAL 71 ІСЇГ/+М \Ctr+Q М. При натисканні клавіші, написаної у складеній команді через пробіл, додаткову клавішу можна відпустити. Наприклад,.для виконання команди Ctr+Q ЛІ натискають Ctr^ і, не підпускаючи її, натискають Q; потік відпускають \Ctrj і Q та натискають X. Усе керування роботою середовища ВР здійснюють, здебільшого, за допомогою системи ієрархічних меню. Кожне конкретне меню - це невеличке вікно з текстом, яке накладається на '(ображення, що є на екрані. Альтернативні варіанти, що містяться в меню, називають опціями (option - варіант), пунктами (меню, підменю) чи режимами меню. Клавіша \F6 з будь-якого рівня меню активізує перехід у попереднє активне вікно. Тобто циклічно перебирає номер вікна і послідовно активізує усі відкриті вікна. Структура меню і робота з ним. Меню системи ВР має деревоподібну структуру, сформовану з головного меню, підменю та їхніх команд. Тут використовують опції (режими) трьох видів: команди, параметри та діалоги. Командами називають пункти меню, що активізують визначені дії системи, а не розгортання чергового підменю. Приклади команд: усі пункти головного меню (верхнього рядка екрана), Run, Trace into, Make та ін. Опція-параметр взаємозв’язана з уведенням числових чи текстових параметрів. Ці опції, зазвичай, належать діалоговому вікну. Опція-параметр має на екрані невеличке додаткове вікно, у яке можна ввести значення параметра. Наприклад, меню File має команду Save as. За її активації на екрані виникає діалогове вікно Save File As (рис. 2.6), у якому є додаткове віконце: у нього необхідно ввести ім’я файла на МД, у який потрібно помістити текст, розташований у вікні редактора. Рис. 2.6. Діалогове вікно Save File As
72 2.3. Робота в інтегрованому середовищі Опціі-діалоги активізують вікно діалогу. Приклад вікна ді^0ГУ - вікно, у якому можна обрати файл для введення його у 0іКНО редактора. Вікно може містити додаткові вікна для введ^0НЯ? наприклад, імені файла, вікна зі списками для вибору з необхідного значення. У вікні діалогу можуть бути кнопки: • для вибору дії (наприклад, OK, Cancel, Help), • для настроювання системи на визначений режим роб°ти* Після успішного запуску системи верхній рядок е*Рана містить набір альтернатив головного меню. Перехід в гоі^ВІ^ меню з будь-якого вікна здійснюють натисканням клавіші цьому випадку курсор потрапляє у рядок головного і^ню’ підсвічуючи один із його пунктів. Він залишатиметься у положенні доти, доки не виконається повернення у вікно реда^Ра чи доки не буде обрано і виконано один з пунктів мен^* . . попереднього рівня меню можна повернутись з допомогою к<ш1 Esc. Вибір необхідної команди головного чи додаткового ^еню здійснюють його підсвічуванням шляхом переміщення курс0ра за допомогою миші чи клавіш керування положенням курсора: . . [<—|. Після вибору необхідного пункту, натискання к#Б1Ш1 активізує розгортання його додаткового мен^ ЧИ виконання певних функцій, якщо цей пункт - команда. Од^ ЦЄ найдовший спосіб активізації меню другого рівня з голо^ного меню. Вибір будь-якого пункту головного меню і розгортання ^еню другого рівня (підменю) після входу в головне меню ^оЖНа здійснити також натисканням першої (виокремленої коль0? літери імені необхідної команди. Наприклад, після входу в г0^овне меню за допомогою Ш натискання літери F спря*"** розгортання меню File другого рівня. Аналогічно, після в меню другого рівня (наприклад, пункту File), натиС^™ виокремленої кольором літери S чи s дає вибір команди Save- і^ал1’ відповідно до тексту позначення команди, меню складав*’08 найменувань пункту меню, підменю і (чи) команди. Наприклад: Run\Step over, Debug\Add watch та ін., де: • Run, Debug - імена пунктів головного меню; • Step over, Add watch - імена команд.
2. МОВА BORLAND PASCAL 73 При розгорнутому підменю головного меню можна перейти до розгорнутого підменю сусіднього пункту головного меню за Tab допомогою клавіші горизонтального переміщення курсора Для розгортання меню другого рівня з будь-якого вікна ссрсдовища краще використовувати команди з клавіші [їй| і першої літери імені пункту головного меню. Призначення пунктів головного меню і команди для переходу у відповідне меню другого рівня наведено у табл. 2.2. Вибір пункту з будь-якого меню натисканням першої літери пункту може не працювати, якщо клавіатура перебуває в режимі введення кирилиці чи в іншому нестандартному режимі. У будь-який момент до завершального натискання клавіші Епіег*\ (для виконання чи команди зміни режиму) можна повернутися в попереднє (чи вихідне) вікно (чи меню) за допомогою клавіші [Еуд або відразу повернутися у вихідне вікно шляхом натискання лівої клавіші миші, коли курсор є на його видимій частині. З вікна діалогу, що має клавіші ОК і CancelІ, можна вийти тільки при натисканні однієї з цих клавіш. Таблиця 2.2 Призначення підменю головного меню Пункт Призначення Команда File Операції з файлами, вихід із системи Ak + F Edit Редагування тексту в активному вікні Ati + E Search Пошук фрагментів тексту, місця розташування помилок Alt + S Run Транслювання, редагування і запуск програми Ak + R Compile Компілювання (транслювання) програми Ak + C Debug Засоби налагодження програм Ak + D Tools Меню інструментальних засобів Ak+T Options Керування параметрами компілювання, компонування і середовища ВР Ak+O Window Керування вікнами Ak+W Help Звертання до системи оперативної допомоги Ak + H
74 2.3. Робота в інтегрованому середовищі Деякі пункти спадних підменю Наприклад: налічують свої підменю. Такі пункти підменю відзначені праворуч темним трикутником. Якщо в рядку пункту підменю присутні три крапки, то внаслідок вибору цього пункту на екрані виникне діалогове вікно. Під час використання меню та вікон пам’ятаймо такі правила: • Перехід з будь-якого вікна в меню другого рівня здійснюють за допомогою команд табл. 2.2. • Вибір команди в підменю здійснюють натисканням на клавіатурі літери з назви цієї команди, виокремленої кольором. • Перехід від однієї команди до іншої виконують клавішами керування положенням курсора. • Перехід від одного меню другого рівня до сусіднього здійснюють натисканням клавіш 0І0- • Обрана (підсвічена) команда буде виконаною, якщо натисгіути клавішу ЕМег*Х чи навести на неї курсор і натиснути ліву клавішу миші. • Відмову від вибору команди і повернення в меню вищого рівня чи в активне вікно екрана здійснюють • клавішею |£жс|. • Перемикання активних вікон - за допомогою команди ЛЙ+М де N- номер вікна. • Перехід з будь-якого вікна до деяких найважливіших команд меню, оминаючи головне і додаткове меню, здійснюють шляхом натискання “гарячих клавіш”. Деталізуємо базові режими текстового меню середовища ВР.
2. МОВА BORLAND PASCAL 75 Робота з файлами Вид підменю File подано на рис. 2.7. Відкрити вікно для нового файла Відкрити існуючий файл Зберегти файл э попереднім іменем Зберегти файл з новим іменем Зберегти файли усіх вікон Змінити активну директорію Друк файла з активного вікна Настроювання принтера Тимчасовий вихід у DOS Вихід з системи Рис. 2.7. Альтернативи підменю File • New - відкриває нове вікно редактора для створення у ньому файла. Новоствореному файлові привласнюють ім’я NONAMEOO.pas. Його можна (і потрібно) змінити під час запису файла на диск. • Open..F3 активізує вікно діалогу з заголовком Open a File для вибору файла і виведення його у вікно редактора. Вікно містить: S вікно-рядок для введення імені файла чи шаблона для виведення списку файлів у вікно вибору імені зі списку; S вікно зі списком директорій та імен файлів відкритого каталогу; S кнопки: Open (відкрити), Replace (замінити), Cancel (скасувати) і Help (<допомога); S інформаційну панель, що описує обраний файл. За допомогою вікна діалогу можна виконати одну з дій: S ввести повне ім’я файла і вибрати кнопки Replace чи Open; S увести шаблон для вибору імені файла зі списку; S натиснути 0 для вибору шаблона чи імені файла з вікна “передісторії*”, тобто зі списку раніше введених шаблонів чи імен; ШКККПШ New Open... f F3 Save :>F2 Save all Change dir * « * Print Printer setup... DOS shell Exit WM VЩ - ШШ л ъл*- Alt+X
76 2.3. Робота в інтегрованому середовищі S вибрати і переглянути директорії і файли зі списку. Для виведення списку імен файлів можна ввести у вікно-рядок ім’я директорії. Під час вибору директорії із шаблоном імен *.* список відображає імена усіх файлів поточної директорії. Клавішами Щ чи [fl можна обрати (підсвітити) ім’я необхідного файла і натиснути EnterЛ Файл буде зчитано у вікно редактора. Інформаційна панель - це два нижні рядки вікна Open a File з інформацією про файл; вона містить повне ім’я файла, дату, час його створення і розмір обраного файла. Відповідно до прокручування імен файлів уміст цього рядка змінюється. • Save F2 - записує файл з активного вікна редактора на диск. Файл записується під ім’ям, що міститься у верхній рамці вікна. Якщо на момент запису файла ім’я його було NONAMEOO.pas, редактор запропонує перейменувати файл. Якщо на диску є однойменний файл, його буде попередньо перейменовано у файл із тим же іменем і розширенням *.Ьак. • Save as - записує файл, що редагується, на диск під новим іменем, тобто створює копію цього файла під новим іменем., Під час вибору цієї команди на екрані виникає додаткове невеличке вікно; у це вікно необхідно помістити ім’я, під яким записуватиметься файл. Потім обрати, і натиснути кнопку |ОА|. За замовчуванням файл отримує розширення *.pas. • Save all - зберігає на диску модифіковані файли з усіх вікон, а не тільки з активного вікна. • Change dir дає змогу встановити поточним каталог, у "якому розміщені файли цієї програми. У цей каталог записуватимуть новостворені файли програм (якщо немає установки директорії для цих файлів у меню Options\Directories). Поточний каталог використовується системою також для показу списку файлів за командою [рЗІ Під час вибору команди Change dir відкривається діалогове вікно. З нього можна змінити каталог одним із двох способів: S ввести ім’я необхідної директорії і натиснути клавішу \Enter*
2. МОВА BORLAND PASCAL 77 S вибрати диск (Drives), а у ньому необхідну директорію, і натиснути кнопку |ОЛ| • Print дає змогу друкувати вміст активного вікна редактора, результатів, у тім числі вікна (Output). • Printer setup - налаштувати принтер для виведення результатів. • DOS shell дає змогу тимчасово вийти із системи ВР без виходу з ОС. Після такого виходу програміст одержує доступ до всіх стандартних засобів DOSy. Для повернення з DOSy в систему вводимо з клавіатури команду Exit. Одержимо екран у тому ж стані, який був перед активізацією цієї команди. • Exit (Alt+X) здійснює вихід із системи ВР. Якщо перед виходом файл, що редагується, не збережено на диску, система видасть запит: “Чи зберегти файл?”. Команду Exit можна виконати за допомогою клавіш 4Й+АІ з будь- якого рівня меню. Редагування файлів. Меню Edit Команди меню Edit подано на рис. 2.8. ИИГТеагЖ"~1гйг Скасувати дію попередньої команди Повторити дію попередньої команди ~ ~ - Вирізати блок і помістити у буфер Скопіювати блок і помістити у буфер ЇЙ 8 вставити блок з буфера Вилучити блок, не записуючи у буфер шшшиишв Show clipboard Подати вміст бу*®Ра Рис. 2.8. Вид підменю Edit За допомогою команд меню Edit можна виконувати обробку блоків тексту програми. Для виокремлення блоку ставимо курсор на його початок або кінець, натискаємо клавішу \Shifjlj і, не відпускаючи її, клавішами керування положенням курсора!«—І ІЇІ Щ 0 формуємо необхідний фрагмент тексту. Це ж можна зробити і за допомогою миші: натиснути ліву клавішу і, не відпускаючи її, зафарбувати
78 2.3. Робота в інтегрованому середовищі необхідний фрагмент. Виокремлений блок можна скопіювати, перемістити, стерти, записати на диск. Увага! Шляхом виокремлення можна скопіювати текст також : з вікна Help, у якому є безліч готових фрагментів програми, які ілюструють можливості мови Pascal. Якщо виокремлений текст вирізано (Cut) чи скопійовано у буфер (Copy), то його звідти можна командою Paste багаторазово вставити в інший файл чи в інше місце цього ж файла. Show clipboard подає вміст текстового буфера (відкриває вікно Clipboard), у якому зберігаються фрагменти тексту, скопійовані у буфер під час сеансу роботи в системі. Для вставки система використовує текст, виокремлений у певний момент. Вікно з вмістом текстового буфера використовують аналогічно будь-якому іншому вікну текстового редактора. Як і в інших вікнах, у буфері можна виокремити текст звичайним способом, після чого використати його в команді Shift+In^ для вставляння у певне місце вікна редактора. Пошук і заміна тексту. Меню Search Меню Search дає змогу виконувати: • пошук заданого фрагмента тексту (Find); • пошук і заміну тексту новим текстом (Replace)', • пошук місця розташування функцій і помилок у тексті програми, виявлених під час компілювання (рис. 2.9). Run Compile Deb Go to line number... 'Show :.cc ii ’ fH Find error... І — 5£й5 Ьг““'г y . ШШШШ И ЙЙ I — Знайти фрагмент тексту Замінити текст новим Повторити попередню команду Перейти до рядка із номером Подати помилку компілювання Знайти місце останньої помилки Знайти підпрограму Попередній браузер Знайти об'єкт Знайти модуль Знайти глобально Знайти символ Рис. 2.9. Вид підменю Search
2. МОВА BORLAND PASCAL 79 і Розглянемо призначення його команд. • Find (знайти) активізує вікно діалогу Find. У ньому можна задати текстовий фрагмент для пошуку його у програмі, а також параметри цього пошуку. Під час активізації команди пошуку у вікно введення автоматично попадає слово, під яким встановлено курсор. За допомогою клавіші Щ можна активізувати список передісторії, з якого можна ввести текст для пошуку. • Replace (заміна) активізує вікно діалогу, у яке можна ввести шуканий текст і текст, яким необхідно його замінити. • Go to line number запитує номер рядка програми, до якого необхідно перейти, і здійснює перехід. • Show last compiler error повторно визначає місце останньої помилки компілювання і видає щодо неї повідомлення. • Find error знаходить у програмі місце останньої помилки етапу виконання програми. З цією метою необхідно задати її адресу в шістнадцятковій системі числення. • Find procedure (знайти процедуру) робить пошук підпрограми за іменем, зазначеним у діалоговому вікні. Працює тільки під час налагодження програми. Компілювання, компонування і виконання програми Виконання програми. Меню Яип Загальний вигляд підменю подано на рис. 2.10. Тут містяться команди управління процесом виконання програми. Компілювання, компонування, виконання Покрокова перевірка програми Покрокова перевірка програми і підпрограм Виконати програму до курсора Перервати трасування програми Встановити параметри програми "Compile Debug Тс Step over FI Trace into F; Go to cursor F* Parameters... Рис. 2.10. Загальний вигляд підменю Run
80 2.3. Робота в інтегрованому середовищі Меню Run дає змогу здійснити такі види обробки програми: • Run - компілювання, компонування і запуск програми на виконання; • виконання різних режимів трасування програми; • задавання параметрів командного рядка. Якщо програма до запуску не готова, тобто не відкомпі- льована і не скомпонована, команда Run виконує компілювання файлів вихідної програми, компонування (редагування зв’язків) і виконання програми, якщо на попередніх етапах не було помилок. Якщо програма уже відкомпільована, то Run запустить її на виконання. Щодо цього використовують параметри, задані за допомогою команди Parameters меню Run. Під час виконання програми і виведення даних на екран здійснюється перехід з вікна редактора^ вікно Output. Перервати компілювання, редагування чи виконання програми можна за допомогою команди Ctrl+Break . Після нормального завершення програми вікно редактора відновлюється і стає таким, яким воно було до моменту звертання до команди Run. Якщо на одному з етапів обробки програми виявлено помилку, обробка припиняється, і у верхньому рядку екрана висвічується повідомлення про помилку. У цьому випадку курсор переміститься до податку помилкового оператора. Підказку щодо помилки можна одержати натисканням \F1 Після висвічування помилки на етапі виконання програми, процес виконання припиняється, керування передається текстовому редактору і курсор встановлюється під першим символом оператора програми, що спричинив помилку, а у вікні Output з’являється повідомлення щодо помилки. Наприклад. Runtime error 200 at ОООО: 0110. Якщо система працює в режимі налагодження і у програмі розставлено точки зупинки, то виконання програми призупиниться перед першим рядком програми, виокремленим червоним кольором. Після цього можна візуально проконтролювати поточні значення змінних, додати чи скасувати точки зупинок і т. д. Продовжити виконання програми можна за допомогою повторної активізації пункту Run (Ctrl+F9) або перейти на покрокове виконання програми.
2. МОВА BORLAND PASCAL 81 Перегляд результатів роботи програми здійснюють комбіна¬ цією клавіш H/l+F5l чи виконанням команди Output підменю Debug. Клавіша |Esc| повертає управління з вікна результатів у вікно редактора. Наступні чотири команди меню належать до трасування програми у процесі її налагодження (Розділ 2.14). • Parameters (параметри) дає змогу сформувати текстовий рядок, що містить параметри виконуваної програми, яка запускається із середовища ВР, так, ніби вони були задані у командному рядку при активізації програми з MS DOS. Під час активізації команди на екрані висвічується додаткове вікно для введення рядка, що формується за тими ж правилами, що й під час запуску програми із середовища MS DOS. Значення параметрів розділяються пробілами. Компілювання програші. Меню Compile Загальний вигляд меню Compile подано на рис. 2.11. Альтернативи цього меню дають змогу виконувати такі види обробки програми: • компілювання, компонування програми і створення файла з розширенням *.ехе; • компілювання і компонування програми, що містить модулі; • визначення початкового файла компілювання; • одержання докладної інформації щодо програми. Компілювання програми з активного вікна Вибіркове перекомпілювання модулів Перекомпілювання усіх модулів Ціль компілювання Задати ім'я базового файла Стерти ім'я базовогофайла Інформація про задіяні програмою ресурси Target... Real Primary file... Clear primary file Information Рис. 2.11. Вид підменю Compile
82 2.3. Робота в інтегрованому середовищі Compile компілює програму з файла типу <ім 9M>.pas, розташованого в активному вікні. Формується виконуваний файл <ім’я>.ехе. Якщо під час компілювання чи компонування виявлено помилкові конструкції мови, компілювання припиняється, у верхньому рядку екрана висвічується повідомлення щодо помилки, а курсор поміщається на початок помилкового фрагмента програми. При цьому необхідно активізувати директиву компілятора Options\Compiler\Debugging\Debug information. Якщо помилок не виявлено, виводиться вікно з повідомленням про успішне {Successful) компілювання. • Make (створити елге-файл) формує виконувану програму: exe-файл. Якщо в процесі компілювання трапляється звертання до підпрограми певного модуля, середовище перевіряє, чи здійснено у вихідному тексті цього модуля будь-які зміни з моменту його останнього компілювання. Якщо зміни відбулися, здійснюється перекомпілювання цього модуля і формування його нового tpu-файла. Однак якщо pas-файл модуля не знайдено, система використовує існуючий tpu-файл без контролю його змін. Make спрощує розробку багатофайлових програм, оскільки завжди компілюється той мінімум файлів, які з моменту останнього компілювання змінено. • Build подібна до опції Make, за винятком того, що з її допомогою виконується пошук і перекомпілювання усіх файлів та модулів, незалежно від того, чи відбулися у них зміни. Якщо під час компілювання за допомогою Make чи Build не виявлено ні /wis-файлів, ні tpu-файлів - необхідних модулів, видається повідомлення про помилку. • Primary file зазначає ім’я початкового файла (головної програми). Якщо задане це ім’я (незалежно від того, яка програма завантажена в редактор), компілювання програми розпочинається з файла, що містить текст головної програми. У редакторі в цей час може розміщатися програма модуля. Якщо початковий файл не зазначено, то компілювання в режимі Run (Ctrl+F9) можна виконувати тільки у випадку, якщо в редактор завантажено головну програму. Компілювання в режимі
2. МОВА BORLAND PASCAL 83 Compile, Make і Build можна виконувати і для програм, і для модулів, завантажених у вікно редактора. • Команда Information видає вікно діалогу з інформацією щодо поточного стану програми і системи. Керування системою ВР. Меню Options Меню Options (рис. 2.12) дає змогу: • встановлювати параметри компілятора і компону- вальника; • керувати середовищем ВР; • перевіряти і зберігати параметри середовища для роботи в наступному сеансі; Вибір більшості команд приводить до відкриття діалогових вікон. Пункти меню, призначені для встановлення параметрів: Компілятора Розмірів пам'яті програми Лінкера (компонувальника) Налагоджувача Каталогів Перегляду об'єктів Інструментальних засобів Оточення Відкрити файл Зберегти параметри середовища Те ж - у файлі з заданим іменем Linker... Debugger... Directories... Browser... Tools... Рис. 2.12. Загальний вигляд підменю Options
84 2.3. Робота в інтегрованому середовищі List. Управління вікнами. Меню Window Команди меню керують віконною системою ВР: Розмістити вікна мозаїкою Розмістити вікна каскадом Закрити всі вікна Оновити екран Змінити чи перемістити вікно Розгорнути або згорнути вікно Активізувати наступне вікно Активізувати попереднє вікно Закрити активне вікно Показати список усіх вікон сеансу Cascade Close all Refresh display Size/Move Ctrl+F5 Zoom F5 Next F6 Previous Shift+F6 Close Alt+F3 — Al t-K) Рис. 2.13. Вид підменю Window Система допомоги. Меню Help Підменю Help (довідка, допомога) дає змогу використовувати систему підказок. Вона містить інформацію з усіма аспектами інтегрованого середовища і системи ВР. Загальний вигляд підменю Help подано на рис. 2.14. lions Window ———— Index Shift+Fl Topic search Ctrl+Fl Previous topic Alt+Fl IJsinq help Files... Ц Compiler Procedures and functions Reserved words Standard units Borland Pa: Error mess About... ; Перелік тем допомоги Тематичний вказівник Допомога на задану тему Допомога на попередню тему Інформація про Help Створення контекстної допомоги Перелік директив компілятора Список процедур і функцій Перелік ключових слів мови Список стандартних модулів Перелік термінів мови Відомості про повідомлення Інформація про систему Рис. 2.14. Загальний вигляд підменю Help Підменю Help містить загальний перелік розділів інформаційної допомоги, у якому можна вибрати необхідний розділ. Після вибору розділу натискання клавіші EnterJj активізує довідку
2. МОВА BORLAND PASCAL 85 наступного рівня. Таким способом можна одержати до 20-ти екранів (рівнів) довідки. Для вибору розділу чи необхідногр його пункту використовують виокремлення відповідного тексту підсвічуванням. Його можна переміщати, за допомогою клавіш керування курсором, за ключовими словами. Окрім цих клавіш для переміщення вікна перегляду текстів з підказкою використовують клавіші Р%Цр, |Нот4> Епс^. Після вибору необхідного елемента натискають клавішу І&ї/ггД На деяких екранах допомоги ключові слова підсвічені. Вони передбачають виклик відповідної додаткової інформації, що деталізує обране поняття. Ключові слова обирають так само, як і розділи в загальному переліку. Для переміщення до попереднього екрана допомоги необхідно натиснути клавіші \ilt+Fl\. Ці правила працюють в усіх видах допомоги. Щоб забрати довідкову інформацію з екрана, необхідно натиснути клавішу Esc чи закрити вікно. Після виходу із системи допомоги можна повернутися до останнього екрана підказки за допомогою команди Alt+Fl і від нього йта далі системою підказок вперед чи назад. • Index відкриває вікно Help. У ньому під заголовком Turbo Help Index в алфавітному порядку розташовано перелік усіх ключових слів, констант, операцій, імен убудованих підпрограм мови і системи, за якими можна одержати довідку. • Topic search тематичний пошук, який дає змогу одержати підказку щодо операторів мови. З цією метою необхідно підвести курсор під ключове слово оператора, за яким потрібна довідка, і активізувати команду \Ctrl+Fl Previous topic відкриває вікно Help з попередньою темою. Після виходу із системи підказки цією командою можна повернутися до останнього екрана довідки. Using help відкриває вікно Help, у якому подано правила використання самої довідкової системи. Коли вікно Help активне, з нього можна копіювати текст і вставляти його так само, як з вікна редактора.
86 2.4. Елементи мови Borland Pascal 2.4. Елементи мови Вогіапсі Равсаі 2.4.1. Алфавіт мови Правилами мови Вогіапй Ра8саІ передбачено для написання програм використовувати тільки такі символи: 1) 26 латинських великих літер ABCDEFGHIJKLMNOPORSTUVWXYZ і 26 латинських малих літер abcdefghijklmnopqrstuvwxyz\ 2) знак _ (нижнє підкреслення), який використовують замість літери; 3) 10 арабських цифр: 012 3 45 6 78 9 ; 4) знаки операцій: + - * / = <> < > <== >= := @ ; 5) обмежувачі: . , ? ()[](••){}(**)•• : ; 6) специфікатори: Л # $ ; 7) зарезервовані (ключові) слова мови Borland Разсаі використовують для позначення конструкцій мови (їх не можна використовувати як назви змінних, у ролі ідентифікаторів). Примітка: пари символів <> <= >= := (. .) (* *) є неподільними, тобто пробіл між ними вставляти не можна. Пара символів: (. еквівалентна символу [ ; .) еквівалентна символу ] ; (* еквівалентна символу { ; *) еквівалентна символу } . Окрім перелічених, до множини базових символів зачислено пробіл, який при написанні програми на папері прийнято позначати так: 1—*. Пробіли не можна використовувати усередині здвоєних символів і зарезервованих слів. За необхідності використати пробіл всередині ідентифікатора його замінюють символом
2. МОВА BORLAND PASCAL 87 2.4.2. Ключові слова № і і/ii Назва ключового слова Що означає (де вживається) 1 And Логічна операція І 2 Asm Приєднання до PascaZ-програми фрагменту на Асемблері 3 Array Масив даних 4 Begin Початок програмного блока 5 Case Оператор варіанта 6 Const Опис констант 7 Constructor Конструктор (тип процедури в об’єктноорієнтованому програмуванні) 8 Destructor Деструктор (“збирач сміття” в об’єктноорієнтованому програмуванні) 9 Div Цілочисельна операція ділення без остачі 10 Do Виконай (закінчення оператора циклу For) 11 Downto Зменшити до (частина оператора циклу For) 12 Else Інакше (частина оператора розгалуження If) 13 End Завершення програмного блока 14 File Файл (набір даних на зовнішньому носії чи пристрої) 15 For Для (початок оператора циклу з відомим числом повторень) 16 Function Функція (один із двох видів підпрограми) 17 Goto Оператор безумовного переходу 18 V Якщо (частина оператора розгалуження) 19 Implementation Початок другого розділу модуля (“невидимої” його частини) 20 In Приналежність (операція над множинами) 21 Inherited Успадкування (в об’єктноорієнтованому програмуванні) 22 Inline Оператор вставлення машинних кодів у програму 23 Interface Початок першого розділу модуля (“видимої-” його частини) 24 Label Опис міток 25 Library Бібліотека (DLL) 26 Mod Цілочисельна операція отримання залишку від ділення 27 Nil Константа - порожнє значення вказівника 28 Not Логічна операція заперечення 29 Object Об’єкт (початок його опису) 30 Of Належність ЗІ Or Логічна операція АБО 32 Packed Упакований (вживається при описі масивів) 33 Procedure Процедура (один із двох видів підпрограми)
88 2.4. Елементи мови Borland Pascal № п/п Назва ключового слова Що означає (де вживається) 34 Program Заголовок головної програми 35 Record Запис (структурований тип даних) 36 Repeat Повторюй (початок циклу з післяумовою) 37 Set Множина (тип даних) 38 Shi Порозрядне зсування ліворуч 39 Shr Порозрядне зсування праворуч 40 String Рядковий символьний тип 41 Then Тоді (друга частина оператора розгалуження І/) 42 To До (частина оператора циклу Гог) 43 Type Тип (початок опису нестандартних типів даних) 44 Unit Заголовок моду ля 45 Until Доки не (закінчення циклу з післяумовою) 46 Uses Під’єднання модулів до програми 47 Var Початок розділу опису змінних 48 While Доки (початок циклу з передумовою) 49 With Оператор приєднання (для роботи з записами) 50 Xor Логічна операція заперечення АБО 2.4.3. Елементарні конструкції , Елементарні конструкції мови Разса/ формуються із імен, чисел і рядків. Імена (іідентифікатори) слугують для присвоєння назв таким елементам мови, як: • константи; • мітки; • власні типи даних (ті, що створені програмістом); • * змінні; • процедури; • функції; • поля у записах (у складних структурах даних); • модулі; • об’єкти. їм \я - це послідовність літер і цифр, яка починається з літери і не містить пробілів. В іменах можна використовувати символ (нижнє підкреслення). Ім’я може містити будь-яку кількість символів, однак значущими є перші 63 символи.
2. МОВА BORLAND PASCAL 89 Увага! Компілятор мови BP не розрізняє в іменах великих і малих літер. Заборонено у програмі, написаній мовою Pascal, використовувати в ролі імен службові слова та імена, якими названо стандартні константи, типи, процедури, функції і файли. Для поліпшення наочності програми в неї можна уставляти пробіли. Принаймні один пробіл доцільно використовувати між двома послідовними іменами, числами, службовими і стандартними іменами. Приклади імен, що відповідають правилам мови Pascal. А Ь12 rlm SIGMA gamma 180 . Числа у мові Pascal, зазвичай, записують у десятковій системі числення. Вони можуть бути цілими і дійсними. Додатний знак числа можна опустити. Цілі числа записують без десяткової крапки. Наприклад: 217 або -45, або 8954, або +483. Цілі числа в пам’яті комп’ютера представляються точно. Дійснічисла записують з десятковою крапкою або з використанням символа десяткового порядку е: 28. б або о. 65, або -о. 018, або 4. о, або 5Е12, або із. іе-и. Останні два числа можна ще записати так: 5000000000000; 0.000000000731. Дійсні числа в пам’яті комп’ютера представляються наближено, з точністю, яка залежить від типу змінної, значенням якої слугує зазначене число. Pascal допускає запис цілих чисел і фрагментів дійсних чисел з порядком у шістнадцятковій системі числення. Ознакою шістнадцяткового числа є наявність на його початку символу $. Наприклад: $7е $40 $авсо. Рядок у мові Pascal - це послідовність символів, записаних між двома апострофами (')• Якщо усередині рядка необхідно вжити апостроф, то записують два апострофи підряд. Приклади рядків: 'рядок' 'string' 'програма' ' комп' 'ютер'. Зазначимо, що правилами мови Pascal у рядках використання кирилиці не заборонено.
90 2.4. Елементи мови Borland Pascal 2.4.4. Поняття типу для даних У математиці прийнято класифікувати змінні відповідно до їхніх певних важливих характеристик. Існує суворе розмежування: між дійсними, комплексними і логічними змінними; між змінними, що представляють окремі значення і множину значень і т. д. Під час обробки даних на ЕОМ така класифікація є необхідною. У будь-якій алгоритмічній мові кожна константа, змінна, вираз чи функція бувають певного типу. Типи даних у мові Разсаі відіграють надзвичайно важливу роль, оскільки Разсаі спеціально розроблено як засіб для навчання програмуванню. Відомо, що програміст-початківець легко може зробити помилку чи описати свої дії неточно. Отож, компілятор мови Разсаі повинен володіти засобами контролю за діями програміста з метою вчасного запобігання наслідків допущених помилок. Спочатку типи, власне, і призначали для того, щоб програміст міг конкретно вказати компілятору, якого розміру пам’ять необхідна його програмі і що він хоче робити із вмістом цієї пам’яті. Практика застосування типів засвідчила їхню високу ефективність для захисту програми від випадкових помилок. Отож, практично всі сучасні мови програмування тією чи іншою мірою реалізують механізм типів. У мові Разсаі існує правило: щоб використовувати у програмі змінну, її необхідно описати, зазначаючи її тип. Концепція типу мови Разсаі має такі головні властивості: • будь-який тип даних визначає множину значень, до якої або належить деяка константа, або яку може набути * змінна чи вираз, або виробляти операція чи функція; • тип значення, заданого константою, змінною чи виразом, можна визначити або з їхнього виду, або за їхнім описом; • кожна операція чи функція вимагає від програміста, щоб він задав аргументи фіксованого типу і, після закінчення роботи видає результат фіксованого типу. Звідси випливає, що компілятор може використовувати інформацію щодо типів, заданих у нашій програмі, з метою перевірки того, чи написана нами алгоритмічна конструкція є правильною і чи її можна виконати.
2. МОВА BORLAND PASCAL 91 Тип визначає: • множину можливих значень змінних, констант, функцій, виразів, що належать до цього типу; • внутрішню форму представлення даних у пам’яті; • операції та функції, що можуть виконуватися над величинами, що належать до цього типу. Обов’язковий опис типу спричинює інформаційну надмірність у тексті програм. Однак ця надмірність є важливим допоміжним засобом розробки програм і розглядається як необхідна властивість сучасних алгоритмічних мов високого рівня. Мова Pascal налічує скалярні та структуровані типи даних. До скалярних типів зачислено стандартні типи і типи, визначені користувачем. Скалярні типи налічують цілі, дійсні, символьний, логічні й адресний типи. Типи, зумовлені користувачем, - перераховувальні та інтервальні [13, 36, 97]. Структуровані типи мають чотири різновиди: масиви, множини, записи і файли. Окрім перелічених, до мови ВР належать ще два типи - процедурний і об’єктний. З групи скалярних типів можна зазначити порядкові типи, які відзначаються такими властивостями: • усі можливі значення порядкового типу - це обмежена упорядкована множина; • до будь-якого порядкового типу можна застосувати стандартну функцію Ord, яка повертає порядковий номер конкретного значення у цьому типі; • до будь-якого порядкового типу можна застосувати стандартні функції Pred і Succ, які повертають попереднє і наступне значення, відповідно; • до будь-якого порядкового типу можна застосувати стандартні функції Low і High, що повертають найменші і найбільші значення величин цього типу. У мові Pascal уведено поняття еквівалентності і сумісності типів. Два типи ті і Т2 є еквівалентними (ідентичними), якщо виконується котрась з умов: • ті і Т2 визначені з допомогою одного імені типу;
92 2.4. Елементи мови Borland Pascal • тип Т2 описано з використанням типу ті за допомогою рівності або послідовності рівностей. Наприклад: Туре ТІ = Integer; Т2 = ТІ; ТЗ = Т2; . Дещо пом’якшені обмеження визначені сумісністю типів. Наприклад, типи є сумісними, якщо: • вони еквівалентні; • є обидва або цілими, або дійсними; • один тип - інтервальний, інший - його базовий; • обидва інтервальні з загальним базовим; • один тип - рядковий, інший - символьний. У Borland Pascal обмеження на сумісність типів можна обійти за допомогою приведення типів. Приведення типів дає змогу розглядати ту саму величину в пам’яті ЕОМ як таку, що належить різним типам. Щодо цього використовують конструкцію: їм'я_типу (<змінна чи значення>) Наприклад, integer (' z') - це значення коду символу 'Z' у двобайтовому представленні цілого числа, а Byte (534) видає значення 22, оскільки ціле число 534 має тип Word і займає два байти, а тип ВуЩ займає один байт, і в процесі приведення старший байт буде відкинуто. 2.4.5. Скалярні типи даних До .скалярних типів даних належать цілочисельні, дійсні, логічні, символьний і адресний типи. 1. Цілочисельні типи визначають константи, змінні і функції, значення яких належать множині цілих чисел, припустимих для цієї ЕОМ. Назва Характеристика числа Діапазон зміни Пам’ять (байти) Byte Коротке беззнакове 0.. 255 1 Shortlnt Коротке зі знаком -128.. 127 1 Word Звичайне беззнакове 0.. 65535 2 Integer Звичайне зі знаком -32768.. 32767 2 Longlnt Довге зі знаком -2147483648.. 2147483647 4
2. МОВА BORLAND PASCAL 93 Над цілими операндами можна виконувати такі арифметичні операції. • + додавання; • - віднімання; ' ’ • * множення; • div ділення без остачі; • mod одержання залишку від ділення. Результат виконання арифметичної операції над цілими операндами е величина цілого типу. Результат виконання операції ділення цілих величин div є ціла частина частки. Результат виконання операції одержання залишку від ділення mod - залишок від ділення цілих. Наприклад: 17 div 2 = 8; 3 div 5 = 0. 17 mod 2 = 1; 3 mod 5 = 3. Операції відношень, застосовані до цілочисельних операндів, дають результат логічного типу True (істина) чи False (хибність). Мова Pascal налічує такі операції відношень: • = рівність; • <> нерівність; • >= більше чи дорівнює; • <= менше чи дорівнює; • > більше; • < менше. До аргументів цілого типу застосовні такі стандартні (вбудовані) функції, результат виконання яких має цілий тип: Abs(x:), Sqr (х), Succ (х), Pred (х), і які визначають, відповідно, абсолютне значення (модуль) числа х, х у квадраті, х + 1, х - 1. Наступна група стандартних функцій для аргументу цілого типу дає дійсний результат: Sin (х), Cos (х), ArcTan (х), Ln (х), Exp (х), Sqrt (х). Ці функції обчислюють синус, косинус і арктангенс заданого в радіанах кута, логарифм натуральний, експоненту і корінь квадратний, відповідно. Результат виконання функції перевірки цілої величини на нспарність Odd (х) має значення: істина (True), якщо аргумент непарний; неправда (False), якщо аргумент парний: X = 5 Odd (х) -» True ; X = 4 Odd (х) —► False.
94 2.4. Елементи мови Borland Pascal Для швидкої роботи з цілими числами визначено процедури, пояснення роботи яких подано праворуч: Іпс (х) ; _> х := х + 1 Іпс (х, N) ; —» х := х + N Dec (х); v - ] ' -> х := х - 1 Dec (х/ N); -» х := х - N. 2. Дійсні типи даних визначають ті дані, що реалізуються підмножиною дійсних чисел, припустимих для певної ЕОМ. Назва Характеристика числа Діапазон зміни Пам’ять (байти) Кількість Цифру мантисі Single Низька точність 1.5Е-45.. 3.4Е + 38 4 7ч-8 Real Звичайна точність 2.9Е-39.. 1.7Е + 38 6 11 -5-12 Double Подвійна точність 5.0Е-324.. 1.7Е + 308 8 15-5-16 Extended Підвищена точність 3.4Е-4932.. 1.1Е+4932 10 19 -5- 20 Comp Ціле у форматі дійсного -2Е + 63..2Е+ 63 8 19-5-20 Тип Real визначено у стандартному Pascal’і і математичним копроцесором не' підтримується. Інші дійсні типи визначені стандартом IEEE 457 і реалізовані на всіх сучасних комп’ютерах. Для їхнього використання за наявності копроцесора чи при роботі на ЕОМ типу 80486 необхідно компілювати програму з ключем { $n+ >, а за відсутності копроцесора - із ключами { $n- ,е+ }. Тип Сотр хоча і належить до дійсних типів, зберігає тільки довгі цілі значення. Над дійсними операндами можна виконувати наступні арифметичні операції, що дають дійсний результат: • + додавання; • - віднімання; • * множення; • / ділення.
2. МОВА BORLAND PASCAL 95 До величин дійсного типу застосовні всі операції відношень, що дають булівський результат (див. нижче). Один з операндів, що беруть участь у цих операціях, може бути цілим. До дійсних аргументів застосовні функції, що дають дійсний результат: Abs (х), Sqr (х), Sin (х), Cos (х), ArcTan (х), Ln (х), Ехр (х), Sqrt (х), Frac (х), Int (х), Рі. Функція Frac (х) повертає дробову частину х, функція Int (х) - цілу частину х. Безаргументна функція Рі повертає значення числа тс дійсного типу. До аргументів дійсного типу застосовні також функції Тгипс(х) і Round (х), що дають цілий результат. Перша з них виокремлює цілу частину дійсного аргументу шляхом відкидання дробової частини, друга - заокруглює аргумент до найближчого цілого. З .Логічні (булівські) типи даних визначають ті дані, що можуть набувати логічних значень True і False. Назва Значенню False відповідає: Значенню True відповідає: Пам’ять (байти) Boolean Число 0 Будь-яке число, окрім нуля 1 ByteBool Число 0 1 WordBool 0 в обох байтах 2 LongBool 0 в усіх байтах 4 До булівських операндів застосовні такі логічні операції: • not - операція побітового інвертування. Застосування її до цілого числа замінює кожен двійковий “0” цього числа на двійкову “1”, і навпаки. Наприклад: not 0 дає -I; not 12 дає -7з; not True дає False. • and - логічна операція І. Виконується згідно з такими правилами: Операнда Результат виконання операції X Y XandY True True True True False False False True False False False False 1 1 1 1 0 0 0 1 0 0 0 0
96 2.4. Елементи мови Borland Pascal • or - логічна операція АБО. Виконується згідно з такими правилами: Операнда Результат виконання операції X Y XorY True True True True False True False True True False False False 1 1 1 1 0 1 0 1 1 0 0 0 • хor - логічна операція заперечення АБО. Виконується згідно з такими правилами: Операнда Результат виконання операції X Y Xxor Y True True False True False True False True True False False False 1 1 0 1 0 1 0 1 1 0 0 0 Логічний тип визначено так, що False < True. Це дає змогу застосовувати до булівських операндів усі операції відношень. 4. Символьний тип даних визначає упорядковану сукупність символів припустимих у певній ЕОМ: Назва Діапазон зміни Пам’ять (байти) Char Кодова таблиця ПК С256 символів коду ASCIT) 1 Значення символьної змінної чи константи - це один символ із припустимого набору. Символьну константу можна записувати у тексті програми трьома способами: • як один символ, взятий в апострофи. Наприклад’. 'А' ’а' 'ю' 'ю'; • за допомогою конструкції виду #к, де к - код відповідного символу (у цьому випадку значення к перебуватиме у межах 0..255);
2. MOB A BORLAND PASCAL 91 • за допомогою конструкції виду Ас, де с - код відповідного керуючого символу (у цьому випадку необхідно, щоб значення с було більшим, ніж код керуючого символу, на число 64). До величин символьного типу застосовні всі операції відношень. До цих величин визначені дві функції перетворення Ord (с) та Chr (k). Перша функція визначає порядковий номер символу с в наборі символів, друга визначає за порядковим номером попередній символ, розташований на k-му місці в наборі символів. Порядковий номер має цілий тип. До аргументів символьного типу застосовують функції, які визначають попередній і наступний символи: Pred (с), Succ (с). Наприклад: Pred ('F1)=1E'; Succ (1Y1)='Z'. За відсутності попереднього чи наступного символів значення відповідних функцій не визначено. Для літер з інтервалу 'a1..'z' застосовна функція UpCase (с), що переводить ці літери у верхній регістр 'А'..^1. 5. і Рядкові типи даних Назва Діапазон зміни Спосіб використання String Рядок ASCII-кодхв 128 символів, якщо не зазначено їхньої меншої кількості Pchar Рядок Л5С//-кодів Для створення ]¥іпйош- додатків 6. Вказівник - тип даних, який описано службовим словом Pointer. Значеннями змінних і констант цього типу є адреса деякої комірки оперативної пам’яті. Довжина змінної-вказівника дорівнює 4 байти: 2 старших байти містять адресу початку сегмента пам’яті довжиною 64Кб, а 2 молодших - величину зміщення від початку сегмента до точки перебування об’єкта, який адресується. Роботу з адресними змінними (вказівниками) розглядатимемо пізніше. Зазначимо, що для одержання значення адреси будь-якої змінної введено унарну операцію @ . 7. Текстовий тип. Описано службовим словом Text. Використовують для опису текстових файлів. Його детальне пояснення див. у розділі 4.8. Файли. 4 7-451
98 2.4. Елементи мови Borland Pascal 2.4.6. Константи Тип константи у мові Pascal визначають за її написанням: • константи цілого типу - це цілі числа, що не містять десяткової крапки; • константи дійсного типу - дійсні числа, які записано у будь-якому допустимому правилами мови форматі; • логічні константи - логічні значення True і False; • символьні константи - рядки довжиною в один символ, або конструкції виду #к чи Лк. Мова Pascal допускає використання синонімів для позначення констант, у цьому випадку текст програми містить розділ опису констант. Наприклад. Const х = 12.5, t = 'Значення';. 2.4.7. Вирази Вираз складається з констант, змінних, назв функцій, знаків операцій і дужок. Вираз задає правило обчислення деякого значення. Порядок обчислення визначається пріоритетністю операцій, які містяться в ньому. У мові Pascal прийнято такий чотирирів- невий пріоритет операцій: 1-й рівень —» унарні операції: not унарна операція заперечення; - унарний мінус; @ - узяття адреси. 2-й рівень —» операції типу множення: • - множення дійсних і цілих чисел; / - ділення дійсних чисел; div - ділення без остачі цілих чисел; mod - отримання залишку від ділення цілих чисел; and - логічне множення; shl зсування цілого числа вліво на один двійковий розряд; shr зсування цілого числа вправо на один двійковий розряд; 5-й рівень -> операції типу додавання: + додавання дійсних і цілих чисел; - віднімання дійсних і цілих чисел;
2. МОВА BORLAND PASCAL 99 or - логічне додавання; хог - заперечення логічного додавання; 4-й рівень —> операції відношень: = - дорівнює; <> - не дорівнює; < - менше; > - більше; <= - менше або дорівнює; >= - більше або дорівнює; in - приналежність до множини. Вирази входять до складу багатьох операторів мови Pascal. Вони також можуть слугувати аргументами вбудованих функцій. 2.4.8. Бітова арифметика Бітову (порозрядну) арифметику введено в мову Borland Pascal з метою забезпечення безпосередньої роботи з двійковими розрядами (бітами). Операції бітової арифметики можна застосовувати тільки до змінних цілих типів. Перша група операцій - логічні операції not, and, or і хог. • Операція not є унарною. Вона змінює кожен біт цілого числа на протилежний, тобто двійковий “0” замінюється двійковою “1”, і навпаки. • Операції and, or і хог - бінарні. Операнди цих операцій - цілі числа однакового типу. Операції виконуються попарно над усіма двійковими розрядами операндів. Друга група операцій - це операції зсування ліворуч shl і зсування праворуч shr : м shl N ; м shr N. Ці операції зсувають двійкову послідовність значення змінної М, відповідно, ліворуч або праворуч на N двійкових розрядів. Під час зсування ліворуч біти, що виходять за межі розрядної сітки, губляться, а розряди, що звільнилися, заповнюються нулями. Під час зсування від’ємних чисел праворуч розряди, що звільнилися, заповнюються одиницями. Ці операції застосовують для швидкого множення і ділення цілих чисел. Зсування двійкових розрядів числа на одну позицію ліворуч передбачає множення цього числа на 2, зсування на дві позиції ліворуч еквівалентне множенню числа на 4 і т. д. Відповідно, зсування числа на К позицій праворуч еквівалентне діленню його на 2к.
100 2.5. Оператори введення і виведення 2.5. Оператори введення і виведення Розглянемо організацію введення і виведення даних з допомогою термінального пристрою. Термінальний пристрій - це пристрій, з яким працює користувач. Найчастіше це екран (дисплей), призначений для виведення даних, і клавіатура - для введення. Введення у пам’ять машини можна здійснювати або з клавіатури, або з магнітного чи оптичного носія, або з порту введення/виведення, який пов’язує наш комп’ютер з вимірювальним пристроєм або (через мережеві засоби) з іншим комп’ютером. 2.5.1. Апаратне забезпечення Виведення інформації на екран ПК забезпечує особливий електронний модуль - відеоадаптер. Він складається із двох частин: СЛГ-контролера (Catod Rate Tube) і відеопам’яті (відеобуфера). У відеобуфері зберігається один або декілька образів екрана. Його розмір може становити 512Кб, 1Мб і більше. Пам’ять відеоадаптера поділено на сторінки, одна з яких є поточною. Відеоадаптер може працювати у текстовому або графічному режимі. У текстовому режимі екран розділено на тексели (знакомісця) по 2Б відеопам’яті кожен. Байт з парною адресою містить ASCII-код символу. Байт з непарною адресою - це атрибут символу (колір, яскравість, мерехтіння). Залежно від типу монітора і контролера на текстовий екран можна вивести 25, 28, 43 або 50 80-символьних рядків. У графічному режимі зображення на екрані формується з крапок - пікселів (PICture ELement), об’єднаних у рядки. Різні адаптери дають змогу виводити на екран різну кількість пікселів, яку визначає відеосгандарт (табл. 2.3).
2. МОВА BORLAND PASCAL 101 Таблиця 2.3 Основні відео стандарти Назва (розмір відео буфера) Роздільна здатність (X*Y) Кількість кольорів CGA 320а200 4 640*200 Монохромний Hercules 720*348 Монохромний EGA 640*350 16 VGA 640*480 16 320*200 256 SVGA (256Кб) 800*600 16 SVGA (512Кб) 800*600 256 TIGA (1024Кб) 1024*768 256 Піксели на екрані монітора нумеруються з 0, починаючи його лівого верхнього кута (рис. 2.15). Деякі графічні процедури використовують невидимий внутрішній вказівник поточної позиції екрана (аналог видимого курсора текстового режиму). Його положення задається щодо лівого верхнього кута екрана 639, в в, 479 639,479 Рис. 2.15. Координати екрана VGA 2.5.2. Введення/виведення текстової інформації Для введення і виведення даних використовують стандартні процедури введення Read і виведення Write, що оперують стандартними послідовними файлами INPUT і OUTPUT. Ці файли розбивають на рядки змінної довжини, відокремлені один від одного ознакою кінця рядка. Кінець рядка задають натисненням клавіші ENTER«- Вхідні дані можна ввести з допомогою однієї з двох процедур введення:
102 2.5. Оператори введення і виведення • оператор Read (Al, А2, АК); виконує читання к значень вхідних даних і присвоювання цих значень змінним Al, А2,..., АК ; • оператор ReadLn (Al, А2, АК); виконує читання к значень вхідних даних, пропуск інших значень до початку наступного рядка і присвоювання введених значень змінним Al, А2,..., АК. Оператор без параметрів ReadLn; після натискання будь-якої клавіші виконує пропуск рядка вихідних даних. При уведенні вхідних даних відбувається їхнє перетворення із зовнішньої форми представлення (текстової) у внутрішню, зумовлену типом змінних. Змінні, що утворюють список уведення, можуть належати або до цілого, або до дійсного, або до символьного типів. Читання вхідних даних логічного типу в мові Pascal неприпустиме. Оператор введення при читанні значень змінних цілого і дійсного типу пропускає пробіли, що передують числу. Водночас ці оператори не пропускають пробілів, що передують значенням символьних змінних, оскільки пробіли є рівноправними символами рядків. Приклад запису операторів уведення: Var a, b : Real; і, j : Integer; С, D : Char; Яеасі(а, і, і); Яеас2(С, Б) ; . Значення вхідних даних можуть відокремлюватися одне від одного пробілами або символами табулювання і Enter < Для виведення результатів роботи програми на екран використовують оператори: • Write (Al, А2,..., АК); - виведення значень змінних А1, А2,..., АК у рядок екрана; • WriteLn (Al, А2, ..., АК); - виведення значень змінних Al, А2, ..., АК у рядок екрана і перехід до початку наступного рядка; • WriteLn; - пропуск рядка і перехід до початку наступного рядка. Змінні, що формують список виведення, можуть належати до цілого, дійсного, символьного чи булівського типів. Як елемент
2. МОВА BORLAND PASCAL 103 списку виведення, окрім імен змінних, можна використовувати вирази і рядки. Виведення кожного значення в рядок екрана відбувається відповідно до ширини поля виведення, зумовленої конкретною реалізацією мови. Форма представлення значень у полі виведення відповідає типу змінних і виразів: / • величини цілого типу виводяться як цілі десяткові числа; • дійсного типу - як дійсні десяткові числа з десятковим порядком; • символьного типу і рядка - як символи; • логічного типу - як логічні константи True і False. Оператор виведення дає змогу задати ширину поля виведення для кожного елемента списку виведення. У цьому випадку елемент списку виведення має вигляд А: ш, де а - вираз чи рядок, ш - вираз або константа цілого типу. Якщо виведене значення займає в полі виведення менше позицій, ніж ш, то перед цим значенням розташовують пробіли. Якщо виведене значення не поміщається в ширину поля ш, то для цього значення буде відведено необхідну кількість позицій. Для величин дійсного типу елемент списку виведення може набути вигляду А:Ш:м> де а - зміна чи вираз дійсного типу; ш - ширина поля виведення; м - кількість цифр дробової частини виведеного значення, ш і м - вирази чи константи цілого типу. У цьому випадку дійсні значення виводяться у формі десяткового числа з фіксованою крапкою. Приклад запису операторів виведення: Var a, b ; Real; Р, Q : Integer; R, S ; Boolean; Т, V, U, W ; Char; WrlteLn (a, b:10:2>; WriteLn (V, Q:Q); WrlteLn (R, S:S); WrlteLn (T, V, U, w;;. 2.5.3. Робота з псевдографікою Середовище BP дає змогу виводити на екран, а також друкувати принтером увесь набір символів із 256-символьної таблиці коду ASCII. Ця таблиця, окрім цифр, латинських та
104 2.5. Оператори введення і виведення кириличних літер, містить так звані символи псевдографіки, завдяки яким у текстовому режимі можна формувати рамки таблиць, заголовки документів, графіки, гістограми. Ці символи відсутні на клавіатурі, отож, для виведення їх на екран використовують такі способи: 1. Використати стандартну функцію Chr, яка належить модулю Crt. Вона повертає один із символів таблиці коду ASCII, номер якого слугує її аргументом. Нижче наведено програму, яка виводить на текстовий екран усі символи псевдографіки. Діапазон їхніх номерів у таблиці ASCII [176..223]. Program XIO_PsevdoGRF; Uses Crt; Var і : Integer; BEGIN TextBackGround (15) ; TextColor (B1ue); ClrScr; Wrlteln (' Коди псевдографіки '); For і := 176 to 223 do Write (' ', і ,1-> ', Chr (i)); Repeat Until KeyPressed , END. Результат її роботи: * Коди псевдографіки 176-> ::: І77-> » 178-> І 179-> І 180-> \ 181-> і 182-> І 1вЗ-> І 184-> =, 185-> fl 18б-> І 187-> ї 188-> ї 189-> * 190-> * 191-> т 192-> 1 193-> 1 194-> т 195-> f 196-> - 197-> + 198-> V 199-> | 20Ö-> Ь 201-> f 202-> * 203-> * 204-> & 205-> = 20б-> 4 207-;> і 208-> А 209-> Т 210-> т 211-> 1 212-> t 213-> f 214-> r 215-> f 216-> $ 217-> ■> 218-> г 219-> | 220-> в 221-> | 222-> | 223-> ■. 2. Номер потрібного символу псевдографіки можна вказати безпосередньо в операторі виведення на текстовий екран. Наприклад: write (#200);. Цей спосіб є не зовсім зручним, оскільки в момент програмування важко уявити, як виглядатиме зображення після його виведення на екран. 3. Можна вставити в оператор виведення псевдографічний символ безпосередньо з клавіатури. З цією метою спочатку
2. МОВА BORLAND PASCAL 105 вмикаємо на клавіатурі режим \NumLock. Ставимо текстовий курсор у потрібну позицію. Потім тиснемо клавішу £їй| і, не відпускаючи її, набираємо на цифровій частині клавіатури, яка розташована праворуч, номер псевдосимволу. Відпустивши рЩ, побачило зображення потрібного символу. Для виведення на текстовий екран усіх 256-ти символів таблиці кодів АЗСІІ можна використати, наприклад, програму: Program Kody_ASCII; Uses Crt; Var і, z, k : Integer; BEGIN ClrScr; { Очищення текстового екрана } Writeln ('Таблиця символів ASCII') ; Writeln ('Для її перегляду тисни Alt+F5') ; Z : = 1 ; К := 12 ; While True do Begin For i:= z to k do Begin If і > 256 then Exit; Write {Chr(i):1, 1 (1,i:3,1)1) {Chr Стандартна . функція одержання символу} End; Z := z + 12 ; К := k + 12 ; Writeln End ; Repeat Until KeyPressed END.
106 2.5. Оператори введення і виведення Приклад. Демонстраційна програма з використанням символів псевдографіки. Program Zastavka; Uses Crt; І Procedure Makew (xs, ys, xk, yk, Fcol, Tcol:Word; $ 7 Ram:Boolean) ; Var і:Integer; Begin TextBackGround (Fcol); TextColor (Tcol); Window (xs, ys, xk, yk); ClrScr; If Ram then Begin GotoXY (1,1); Write (’if1); For і: =1 to 41 do Write (' = '); Write ( V); Write ('I'); GotoXY (1,2) ; For і: =2 to 9 do Begin Write (' ||'); GotoXY (43, i); Write (' ||') ; Write ('I') End; Write (' It*); For і:=1 to 41 do Write ('='); Write < ’Jl • >; Write ('I'); Write ('|'); For і:=1 to 42 do Write ('|'); GotoXY (7,2); Write (' Демонстраційна програма1); GotoXY (8,4); Write (1 Введіть дані:1); GotoXY (4,6); Write (' Кількість періодів'); Window (1,1,80,25); GotoXY (62,18); Write ('('); Delay (5000) End; Window (1,1,80,25); GotoXY (62,18); Write ('I') End; BEGIN ClrScr; MAKEW (19,8,62,18,Blue,Yellow,True); Repeat Until KeyPressed END.
2. МОВА BORLAND PASCAL 107 2.5.4. Графічні засоби середовища ВР Сучасні системи комп’ютерної обробки результатів експерименту чи моделювання фізичних процесів містять засоби відображення своєї j вхідної та вихідної інформації у вигляді двовимірних графіків, тривимірних поверхонь, кругових діаграм, гістограм та ін. Користувач має змогу змінити масштаб зображень, вибрати гаму кольорів, кут просторового повороту тривимірних зображень та друку графічної інформації на принтері. Ми наразі вивчаємо найпростіший випадок: виведення найпростіших елементів на екран /ВМ-сумісного ГЖ засобами мови ВР. Середовище ВР має потужні засоби побудови графічних зображень на екрані ПК, а саме: • графічні процедури і функції, об’єднані в модуль Graph, tpu, • графічні драйвери (файли *.bgi); • графічні шрифти (файли *.сІігу. Інтерфейсна частина Graph, tpu містить список потрібних для роботи і доступних користувачеві констант, серед яких є назви: кодів помилок, які виникають у роботі в графічному режимі (їх можна видати функцією GraphResult); графічних драйверів і режимів; кольорів ліній і символів; типів і товщини ліній; шрифтів; шаблонів зафарбовування ділянок екрана тощо. Детальну інформацію про склад і можливості Graph.tpu можна знайти в | ІЗ, 36, 65], або з допомогою засобів HELP середовища ВР. У складі стандартної поставки ВР є програма BgiDemo.pas, яка, після запуску її на виконання, демонструє графічні можливості ВР. Її розташовано у каталозі ..:\Bp\Examples\Dos\Bgi\BgiDemo.pas. Перед початком роботи програма пропонує ввести шлях до графічного драйвера EgaVgcubgi. Вводимо, наприклад: C:\BP\BGI і натискаємо клавішу Enter J. Нижче наведено мінімальну кількість інформації, знання якої достатньо для побудови найпростіших графічних зображень на екрані ПК з відеоадаптером VGA: 1. Окрім модулів ВР.ехе, TURBO.tpl, TURBOMp та ін., директорії ВР повинні налічувати: • .. \ВР\ UNITS - файл Graph.tpu;
108 2.5. Оператори введення і виведення • .. \BP\BGI - файл драйвера Ega Vga. bgi; • ..\BP\BGI- файли стандартних шрифтів *.chr. 2. В описовій частині Вашої програми: • після її заголовка має бути запис Uses Graph, Crt;, який забезпечує можливість доступу до графічних процедур і функцій та функцій клавіатури; • розділ Var повинен містити описи: S двох змінних цілого типу, якими задають тип графічного драйвера і режим роботи графічного адаптера (наприклад, Drv і Drm); S двох змінних цілого типу, для поточних координат об’єктів, які виводяться на екран: пікселів, тексту та ін. (наприклад: X і Y); S восьми змінних дійсного типу (наприклад, МахХ, MaxY, MinX, MinY, Кх, Ку, Zx, Zy), які міститимуть максимальні і мінімальні значення абсциси та ординати графіка і значення коефіцієнтів масштабування графіка по осях X і Y; S двох масивів дійсного типу розміру [0..640] для запису значень аргумента і функції (наприклад, Хе, Ye). 3. У програмі необхідно використати такі процедури і функції модуля Graph.tpu: Першою за номером обов’язковою графічною процедурою є процедура перемикання адаптера з текстового режиму в графічний: * JnitGrąp2i(Drv, Drm, ' С: \BP\Bgi') ; I I |-> шлях до драйвера EgaVgabgi, I I -» режим робота графічного адаптера; І —> тип графічного драйвера. * Змінним Drv і Drm попередньо присвоюють значення стандартних констант модуля Graph.tpu. Наприклад, щоб одержати режим (640*480) 16 кольорів, задаємо: Drv := VGA; (або Drv := 9/ ) і Drm := VGAHi; (або Drm := 2; ) . Найдоцільніше задавати так: Drv := Detect;.
2. МОВА BORLAND PASCAL 109 У цьому випадку ВР автоматично встановить тип драйвера і задасть оптимальний для нього режим роботи, тобто присвоїть змінним Drv і Drm відповідні значення. . Примітка. Кожна графічна процедура генерує ціле число - код результату її виконання. Його можна одержати, використавши функцію GraphResult. Якщо певна графічна процедура виконалась безпомилково, то значення функції GraphResult становитиме 0. В іншому випадку - це від’ємне число, за яким можна розпізнати помилку. Наприклад: Після активізації процедури InitGraph у програмі доцільно виконати такі оператори: If GraphResult О 0 then Begin Writeln('Помилка при вмиканні графічного режиму'); j Writeln('Код помилки = ',GraphResult) End; При вирахуванні коефіцієнтів масштабування даних, перед їхнім виведенням на екран, необхідно використати функції GetMaxX і GetMaxY, які видають цілочисельні значення максимальної кількості пікселів по осях X і Y, відповідно, у поточному режимі роботи графічного адаптера. Задавши колір лінії (обов’язково) і її стиль (необов’язково) процедурами: SetColor (< колір >); І -> вираз типу Word, який задає колір графічного об’єкта, що виводиться; SetLineStyle (<вид>, <ЗраЗок>, <товщина>); І І 1-^1 або 3 піксели; І І —> використовується для ліній, заданих І користувачем (якщо вид = 4); І -» 0 - суцільна лінія; 1 - точкова; 2 - пггрихпунк- тирна; 3 - пунктирна; 4 - вид лінії задає користувач, виконують побудову осей координат процедурою креслення лінії: Line (XI, Yl, Х2, Y2); тут XI, Y1 - координати початку лінії, X2,Y2 - координати її кінця.
110 2.5. Оператори введення і виведення Побудову графіка можна здійснити, виконуючи в циклі: • або процедуру виведення пікселів: PutPixel (X, Y, < колір >);, де X, Y - поточні екранні координати піксела; <колір> - його колір. • або процедуру виведення відрізків ліній: LineTo (X, Y) де X, Y - координати кінця відрізка. Координати його початку - це або попереднє значення вказівника, або його положення, встановлене процедурою: МотгеГо (X, Y) • або - геометричних фігур, для викреслювання яких Graph.tpu містить відповідні процедури. Наприклад, процедура, яка викреслює коло: Circle (X, Y, < радіус >);, де X, Y - координати центра кола; <радіус> - радіус кола у пікселях. Зміну значення х і Y здійснюють послідовним зчитуванням відповідних елементів аргумента і функції з масиву або файла. Якщо ці значення дійсного типу, то їх переводять у цілочисельне представлення функціями: Тгипс (<значення>) або Round (<значення>). Примітка. Якщо на екран потрібно вивести 2 або більше графіки, то доцільно застосовувати різні кольори або різні геометричні фігури (кола, еліпси, прямокутники). Щодо цього, коефіцієнти масштабування необхідно вираховувати, відповідно, за найбільшим і найменшим значеннями, визначеними при обробці всіх числових масивів, графіки яких повинні бути одночасно виведені. Графік відображатиме не лише якісну, а й кількісну характеристику процесу, якщо на осі координат нанести масштабні поділки (із числовими значеннями ціни поділки). ВР дає змогу виводити на графічний екран текстову інформацію різними графічними шрифтами як у горизонтальному, так і у вертикальному напрямах. У стандартному наборі графічних шрифтів ВР відсутні символи кирилиці. Отож, для виведення написів українською
2. МОВА BORLAND PASCAL 111 мовою у директорії ..\BP\BGI стандартні шрифти необхідно замінити шрифтами розширеними, які містять кирилицю. Виведення тексту на графічний екран здійснює процедура: OutTextXY(X, Y, < текст »} І І —> вираз типу String або Char; і І —»екранні координати початку текстової інформації. Перед виведенням необхідно встановити стиль і розмір тексту процедурою: Se tTextStyle (<шрифт> , <налрям> , <розм±р>) ; І І І -»число з діапазону 1..10; I I -» 0 - зліва праворуч; 1 - знизу вгору; І —> число з діапазону 0..4; (0 - стандартний шрифт розміром 8*8 пікселів; 1, 2, 3, 4 - штрихові шрифти, відповідно, таких типів: триплекс, зменшений, прямий, готичний). Для виведення чисел на графічний екран спочатку їх перетворюють із внутрішнього представлення у символьне процедурою: Str (< змінна >, < текст >) ; І І -» змінна типу String9 яка містить текст числа; І —» змінна типу Real або Integer, значення якої виводиться. Примітка. Під час перетворення дійсного числа перший параметр процедури Str можна задати так: < змінна >:< ширина >:< кількість >, де <ширина> - кількість символів, яку буде виокремлено під представлення дійсного числа у текстовій формі; <кількість> - кількість символів у дробовій частині результату. Перехід з графічного режиму в текстовий здійснює процедура CloseGraph.
112 2.6. Структура програми 2.6. Структура програми Програма, написана мовою Pascal, налічує: • заголовок; • розділ описів; • розділ операторів. Заголовок програми містить ключове слово Program, за яким іде ім’я програми. Наприклад: Program Prim;. Наявність заголовка не є обов’язковою, проте бажаною. У розділі описів можуть бути такі підрозділи: • Uses - підрозділ підключення бібліотек (модулів). Містить імена модулів, які підключає програміст до своєї програми. Модулі бувають стандартними (такими, щр належать до бібліотек системи ВР) і власними (створеними автором чи іншими програмістами). Імена модулів у рядку Uses відокремлюють одне від одного комами. Увага! Розділ Uses необхідно розташовувати одразу після заголовка програми. Наприклад, речення: Uses Crt, Graph, My_GRF; задає компілятору вказівку під’єднати до програми два стандартні модулі Crt і Graph і один власний модуль під назвою My_GRF. • Label - розділ опису міток. Будь-який виконуваний оператор програми можна виокремити міткою, яка складається із довільної комбінації літер або цифр кількістю не більше чотирьох і відокремлюється від оператора символом (двокрапка). Усі мітки, які планують використати у програмі, необхідно перелічити у розділі Label. Наприклад: Label З, 471, М29, Quit; . • Const - розділ опису констант. Опис констант дає змогу використовувати в програмі їхні імена як синоніми констант. Наприклад: const к = 1024; мах= 16384;
2. МОВА BORLAND PASCAL 113 • Type - розділ опису типів даних, які задає програміст. Наприклад: Type Vector = Array [1. .10] of Real; описує набір (масив) дійсних чисел як єдину структуру даних. • Var - розділ опису змінних. Тут необхідно перелічити імена усіх змінних, які використовуватимуть у програмі, )і зазначити тип кожної з них. Опис змінних одного типу / можна групувати, розділяючи їхні імена комами: Наприклад. Var Р, Q, R: Integer; {опис трьох змінних цілого типу} А, В: Char; {опис двох символьних змінних} FI, F2: Boolean; {опис двох логічних змінних}. • Procedure і (або) Function - розділ опису процедур і функцій. Правила їхнього опису розглядатимемо нижче. Окремі розділи описів можуть бути відсутніми. Увага! У Pascal-програмі необхідно обов’язково описати усі її власні компоненти. • Розділ операторів - це складений оператор, що міститься між службовими словами: BEGIN ... {тут знаходиться послідовність операторів, відокремлених один від одного символом 0} END. {<— Текст програми завжди закінчується END.} . Окрім описів та операторів Pascal-програма, може містити коментарі як довільну послідовність символів коду ASCII (American Standard Code for Information Interchange), розташовану між відкриваючою —» { і закриваючою -> } фігурними дужками. Коментарі можна вводити у будь-якому місці програми окремими рмдками чи як пояснення збоку операторів. Приклад запису простої програми з коментарями, яка обчислює півсуму двох дійсних чисел і виводить її на дисплей:
114 2.6. Структура програми Program First; {Заголовок програми. First -> її ім'я} {Описова частина програми >1} Uses Crt; {Під'єднання стандартного модуля Crt } Var а, b, с : Real; {Опис трьох змінних а,Ь,с дійсного типу} BEGIN {Виконувана частина програми і} а := 7.3; {Присвоєння змінній а значення 7.3} b := 2.7; {Присвоєння змінній b значення 2.7} с := (а + Ь) /2; {Обчислення півсуми а і Ь} WriteLn {'с=', с:8:3); {Виведення на екран результату} Repeat Until KeyPressed {Затримка показу результату на екрані} END. Текст PascaZ-програми може також містити директиви компілятора, що дають змогу керувати режимом компілювання. Директива компілятора налічує неподільну послідовність символів: {$<літера-ключ> з наступними символами “+}” (увімкнути режим) чи }” (вимкнути його). Наприклад. { $е+} - виконувати програмне емулювання команд математичного копроцесора; { $f+} - формувати далекий тип виклику процедур і функцій; { $n+} - використовувати математичний копроцесор; {$R+} - перевіряти вихід значень індексів масивів за задані при описі останніх межі діапазонів. Деякі директиви компілятора можуть містити параметр. Наприклад: {$і сім'я файла>} - ввести у текст програми під час її компілювання названий файл. Такі директиви використовують з метою долучення до описового розділу програми процедур і функцій, тексти яких записано в окремих файлах на диску.
2. МОВА BORLAND PASCAL 115 2.7. Підпрограми Якою б універсальною не ’ була мова програмування, безпосереднє розв’язання з її допомогою задач кожної конкретної предметної області може спричинити до надто громіздких програмних конструкцій. Однією з найважливіших властивостей мови програмування є можливість побудови, з допомогою її іасобів, окремих алгоритмічно завершених структур, які називають підпрограмами. Розглянемо просту до банальності чадачу. Нехай нам необхідно намалювати на графічному екрані ПК п’ять квіток, кожна з яких розташована в різних частинах екрана (наприклад, так, як це показано на малюнку). Не варто програмувати окремо виведення кожної з цих графічних фігур. Краще створити фрагмент програми для малювання однієї квітки, а потім виконати його необхідну кількість разів, змінюючи координати центра фрагмента. Оформлений відповідно цей фрагмент і слугуватиме підпрограмою. Підпрограму можна порівняти з приспівом пісні. У тексті пісні його пишуть лише один раз, а при виконанні повторюють декілька разів. Мова Раясаі володіє двома типами підпрограм: • процедури-, • функції. Ці обидві структури близькі як за конструкцією, так і за використанням, однак кожна з них має свою специфіку. Процедури і функції є зручним засобом для однократного автономного опису тих фрагментів програми, які повторюються в різних частинах її алгоритму. Такі описи утворюють розділ, який необхідно розташувати останнім із переліку описових розділів програми. Можливість виокремити у складному алгоритмі допоміжні простіші алгоритми (що при програмуванні виражається у використанні процедур і функцій) дає змогу робити програму етруктурованою і, як наслідок, легшою для читання, простішою для налагодження та модифікування, а, отже, дещо надійнішою.
116 2.7. Підпрограми Підпрограма володітиме переліченими вище позитивними властивостями, якщо розмір окремої процедури чи функції не перевищуватиме деякого максимального розміру - порядку 50-60 рядків (одна сторінка тексту). Програму, яка налічує процедури і функції, називають модульною. Модулі такої програми можуть налічувати дрібніші модулі. Отож, модульна програма має ієрархічну структуру. Важливо, щоб кожна з підпрограм виконувала закінчену, чітко окреслену дію, суть якої бажано відобразити в імені цієї підпрограми. 2.7.1. Процедури Процедурою в мові Pascal називають послідовність операторів, оформлену певним однозначно заданим способом, якій присвоєно унікальне ім’я. Щоб виконати цю послідовність у потрібному місці головної програми, у цьому місці необхідно написати ім’я процедури. Таке звертання до процедури називають оператором виклику процедури. Компілятор мови Borland Pascal містить чималу кількість вбудованих стандартних процедур і функцій. Доступ до частини з них можна здійснити безпосередньо. Інша частина вимагає, щоб після заголовка головної програми був присутній запис Uses, після якого через кому подані назви стандартних бібліотек, процедури і функції яких ми використовуватимемо у нашій програмі. Наприклад, запис Uses Crt, Graph; дає змогу використовувати процедури і функції стандартних бібліотек Crt і Graph. Використання процедур надає змогу програмістові: • присвоїти деякій послідовності операторів ім’я; • "вилучити цю послідовність з виконуваної частини програми і розташувати її в описовому розділі; • за посередністю її імені передавати управління цьому фрагменту програми у тих місцях головної програми, де виникає необхідність у виконанні цього фрагмента. На рис. 2.16 проілюстровано, як взаємодіє процедура МуРгос з головною програмою. Як бачимо, текст процедури МуРгос розташовано в описовій частині головної програми після опису змінних.
2. МОВА BORLAND PASCAL 117 Початок описового блоку головної програми Опис нашої процедури Виклик нашої процедури Закінчення головної програми Program First; Uses ^Const.... Label.... Type.... Var ^Procedure MyProc; Var.... Begin- <тіло процедури> "nd; * +BEGIN <onepamopu> r<onepamop>— END. Рис. 2.16. Взаємозв’язок процедури MyProc з головною програмою Послідовне виконання операторів головної програми позначено стрілками. З місця перебування оператора виклику процедури управління передається тілу процедури. Після виконання операторів тіла процедури управління повертається до оператора, який є наступним після виклику процедури МуРхос. За своєю конструкцією розрізняють процедури без параметрів і з параметрами. Опис процедури без параметрів: Procedure Сім'я процедури>; [Сописова частина процедури>] Begin Соператорна частина процедури> End; <ім’я процедурні — будь-який ідентифікатор, побудований за правилами мови Pascal. Тілом процедури називають послідовність операторів зі структурою, яка збігається зі структурою головної програми. Вона МІСТИТЬ НЄ обов’язкову Сописову частину процедури> І обов’язко-
118 2.7. Підпрограми ву виконувану <операторну частину процедури^ яку розташовано всередині операторних дужок: Begin < операторна частина (тіло) процедури > End; Зауважимо, що процедура самостійно (окремо від головної програми) виконуватись не може. Вона є частиною головної програми і міститься в її описовому розділі. Як і всі інші елементи цього розділу, процедура не виконує жодних дій. Процедура виконується тоді, коли її ім’я як оператор процедури записано у тілі програми. Розглянемо використання процедур без параметрів на прикладі: Скласти програму, що виводить на екран таблицю з N значень одного періоду синуса кута. Розглянемо два варіанти програми розв’язання цієї задачі: без використання процедур та з їхнім використанням. 2.7.2. Програма табулювання функції Без використання процедури Program Tabul_Sin; Uses Crt; Const N = 12; Var і : Integer; x, y, h, a, b : Real; BEGIN* ClrScr; a :=0; b := 2*Pi; {Межі зміни аргументу - період} h := (b - а) / N; {Крок зміни аргументу } Writeln (' Результат табулювання y=Sin(x) '); Ж* ї'-І і* , Writeln(1 Кут Синус 1 ); З використанням процедури Program Tabul_Sin_Proc ; Uses Crt; Const N = 12; Var і : Integer; x, y, h, a, b : Real; Procedure DrawDLine; Begin BEGIN ClrScr; a := 0; b := 2 * Pi; {Межі зміни ' аргументу - період} h := (b - а) / N; {Крок зміни аргументу } ^ Writeln{' Результат табу- t§§|
2. МОВА BORLAND PASCAL 119 fetimi x : =a ; For i := 0 to N do Begin j y : = Sin ( xr ) ; Writeln ( x , y ); x := x + h End; 4,11 Repeat Until KeyPressed END. лювання у = Sin (x) f); DrawDLine; { Виклик DrawDLine} Wtiteln (f Кут Синус* ); DrawDLine;{Виклик DrawDLine} x : = a ; For і := 0 to N do Begin у := Sin ( x ) Writeln ( x , у ); x := x + h; End; DrawDLine;{Виклик DrawDLine} Repeat Until KeyPressed END. Результат табулювання у = Sin (x) кут Синус Порівнюючи дві наведені програми, зазначимо, що фрагмент, призначений для малювання рядка з рисок (затемнені ділянки програми), який у програмі таЬиі_зіп повторювався тричі, замінено триразовим звертанням до написаної нами процедури DrawDLine. Використання процедури дає змогу скоротити програму і зробити її зрозумілішою та наочнішою. Якщо ми захочемо змінити довжину рядка рисок, то всі зміни досить провести в процедурі, не звертаючись до головної програми. Окрім того, якщо ми захочемо вивести на екран таблицю значень ІНШОЇ функції, ТО процедуру DrawDLine можна використовувати без будь-яких змін. 0.00000000000000Е+0000 3.49065850398802Е-0001 6.98131700797603 Е-0001 1.047197551197 31Е+0000 1.39626340159703Е+0000 1.74532925199674Е+0000 2.094395102 39463 Е+0000 2.44346095279252Е+0000 2.79252680319041Е+0000 З.14159265358830Е+0000 З.49065850398620Е+0000- 3.83972435438409Е+0000- 4.18879020478198Е+0000- 4.53785605518351Е+0000- 4.88692190558504Е+0000- 5.2 3 59877 5 598657 Е+0000- 5.58505360638810Е+0000- 5.93411945678963Е+0000- 6.283185 30719116Е+0000 0.00000000000000Е+0000 З.42020143325499Е-0001 6.42787609686820Е-0001 8.6602 5403784988Е-0001 9.848077 5 3012 319Е-0001 9.84807753011410Е-0001 8.66025403784079Е-0001 6.42787609685911Е-0001 З.42020143325954Е-0001 1.48870954626290Е-0012 3.42020143323225Е-0001 6.42787609684092Е-0001 8.66025403782260Е-0001 9.84807753012319Е-0001 9.84807753012319Е-0001 8.6602 5403782260Е-0001 6.42787609681363 Е-0001 3.42020143317313Е-0001 1.1574496135841ІЕ-0011
120 2.7. Підпрограми 2.7.3. Локальні і глобальні змінні Як і в головній програмі, в описовому розділі процедури можна описувати константи, змінні, інші процедури і функції. Розділ описів у процедурах має таку ж структуру, як аналогічний розділ у головній програмі. Оголошені усередині процедури змінні називають локальними стосовно цієї процедури: поза нею вони недоступні Операції, що відбуваються з локальними змінними усередині процедури, не впливають на значення змінних з такими ж іменами, проте описаними поза цією процедурою. Змінні, використані у процедурі, однак описані поза нею, називають глобальними стосовно цієї процедури. Будь-яка зміна значення однієї з цих змінних усередині процедури змінює її значення поза процедурою. Вважають, що процедура має “побічні ефекти”, якщо вона змінює значення хоча б однієї глобальної змінної. Зазвичай, побічні ефекти небажані, оскільки вони можуть спричинити до помилок, які важко виправити. Отож, у процедурах рекомендують уникати глобальних змінних і користуватися локальними змінними та параметрами. Приклад програми, що ілюструє принцип локалізації змінних $ Program Loc__P£ram; Uses Crt; Var a, b : Integer; Procedure Loc_Var; Var a, x : Char; Begin І a :=* 1 -1; x := b := b + 1 End; і BEGIN a := 0; b := 100; Loc_Var; Writeln (a,' ', b ) ; Repeat Until KeyPressed » END. Використання глобальних параметрів і у процедурі ti Program Loc__Paraml; Uses Crt; k Var a, b : Integer; I Procedure Loc_Var; Var a, x : Char; Begin End; BEGIN Ц a : = 0; b := 100; Loc_Var; Writeln (a,1 ', b ) ; Repeat Until KeyPressed END.
2. МОВА BORLAND PASCAL 121 Процедура Loc_Var має дві локальні змінні символьного типу: а, х. Головна програма не може змінити їхні значення чи звернутися до них. Змінна b - глобальна для Loc_Var, вона доступна як програміу так і процедурі.* Оскільки у процедурі немає іншого опису для Змінної Ь, то всі зміни, що відбуваються зі значенням b у процедурі, зберігаються і після виходу з неї. Змінна а в головній програмі належить до цілого типу, однак у процедурі Loc_Var описана своя власна змінна а, що належить до типу Char. Змінна а з головної програми не доступна у процедурі Loc_Var. Усі зміни, що відбуваються зі значенням а у процедурі, втрачають свій зміст при виході з неї. Отже, у результаті роботи програми Loc_Param на екран буде виведено два числа: о і іоі. У Borland Pascal введено розширення мови, завдяки якому в процедурі можуть бути доступні як локальні щодо неї змінні, так і змінні з іменами, аналогічними до описаних у головній програмі. Щоб реалізувати таку можливість, звертання до змінної у процедурі виконують у такий спосіб: • до локальних змінних звертання надходить просто за їхнім іменем (тобто як у стандарті мови); • для звертання до змінних, однойменних з локальними, проте описаними в головній програмі, використовують таку форму: Сім' я_програми>. <ім 'я_змінноі>. Тут: сім'я__прогргми> - ім’я програми, зазначене в заголовку програми - Program ; <ім'я_змінної> - ідентифікатор змінної, зазначений у розділі Var опису змінних. Використовуючи цю можливість, програму Loc_Param можна перетворити так, щоб у процедурі Loc_Var були доступні однойменні змінні, визначені як у самій процедурі, так і в головній програмі. У тексті програми, який наведено вище, відповідний оператор виділено. Внаслідок роботи зміненої програми Loc_Paraml на екрані з’являться такі значення змінних: 5 і іоі.
122 2.7. Підпрограми 2.7.4. Процедури з параметрами Процедура DrawDLine, яку ми розглянули вище, має незмінну структуру: вона слугує для виведення рядка символів “=” завжди постійної довжини. У мові Pascal є засоби, що дають змогу зробити процедуру гнучкішою. Цього досягають завдяки використанню у процедурах параметрів. За своїми функціональними ознаками їх поділяють на вхідні і вихідні. Щоб утворити процедуру з параметрами, у заголовку процедури після її назви в круглих дужках зазначають змінні (за допомогою яких процедурі передаються дані) та їхні типи. Зобразимо це схематично: Procedure<±м'я процедури> (<вх±дн± параметри: типи параметрів>; Var <вихідні параметри: типи параметрів>) ; [< описова частина процедури > ] Begin < виконувана частина процедури >; End; Змінні, що фігурують у заголовку процедури, називають формальними параметрами. Змінні чи константи, що фігурують в операторі виклику процедури, називають фактичними параметрами. Під час звертання до процедури з параметрами усі формальні параметри заміняються фактичними в порядку їхнього місцезнаходження в заголовку процедури. Якщо у списку формальних параметрів є декілька змінних однакового типу, їх можна описати списком, розділяючи змінні комою. Використовуючи параметри, процедуру DrawDLine можна перетворити в такий спосіб : Procedure DrawDLinePar ( М, N : Integer; s : Char ); Var j ; Integer; Begin For j := M to N do Write ( s ); Writeln End; Звернення до процедури DrawDLinePar (її виклик) може набути такого вигляду: DrawLinePar ( 10, 25, '=' ); ЧИ DrawLinePar ( L, k, Symb )/.
2. МОВА BORLAND PASCAL 123 Тут Lik- змінні типу Integer:; Symb - змінна типу Char. Такий спосіб передавання параметрів процедурі називають передачею за значенням. У цьому випадку значення фактичного параметра стає доступним для процедури. Його можна використовувати в роботі, змінювати будь-яким способом. Однак ці :іміни проявляються тільки у межах процедури, тобто є локальними. Поза процедурою ці зміни є невидимими. Передати виконані процедурою зміни значення деякого формального параметра значенню фактичного параметра можна так: достатньо перед ідентифікатором формального параметра в заголовку процедури зазначити ключове слово Var, щоб компілятор виконав ототожнення адреси формального параметра з адресою фактичного. У цьому випадку будь-яка зміна значення формального параметра активізує відповідну зміну значення фактичного параметра. Під час програмування доцільно пам’ятати такі правила: 1. Якщо змінну використовують тільки у процедурі і не використовують у головній програмі, то її варто описувати в процедурі. Іншими словами: там, де це можливо, варто використовувати локальні змінні. 2. Щоб уникнути помилок, іменами формальних параметрів рекомендують обирати ідентифікатори, які не використовують у програмі для інших цілей. 3. Під час виклику процедури фактичні параметри необхідно задавати у тому ж порядку, в якому перелічено формальні параметри. У протилежному випадку виникне невідповідність між значеннями фактичних і формальних параметрів. Необхідно дотримуватись суворої відповідності типів формальних і фактичних параметрів. 4. Якщо деякий формальний параметр слугує результатом роботи процедури, то його варто описувати як параметр- змінну. Якщо ж формальний параметр є тільки аргументом (вхідним параметром) процедури, то його варто описувати як параметр-значення. 5. Параметрами процедури можуть слугувати процедури і функції (так званий процедурний тип даних).
124 2.7. Підпрограми 2.7.5. Функції Функції за своїми якостями подібні до процедур. Однак існує принаймні дві особливості, які відрізняють ці два види підпрограм. Увага! Додатково до всього того, що може робити процедура, функція обов’язково формує одне результуюче значення і передає його у точку її виклику, використовуючи своє ім’я. Як наслідок виникають: • розбіжності у заголовках процедур і функцій; • розбіжності у способах виклику цих двох типів підпрограм на виконання. Загалом опис функції набуває такого вигляду: Function <±м1 я функції> [ (<вхідні парамепри>: <типи параметрів>; Var <вихідні парамеіри>: <типи параметрів>) ] : <тип результату>; [< описова частина функції >]/ Begin < виконувана частина функції >; <ім'я функції> := <значення> End; Увага! Нагадаємо, що квадратні дужки в описах вказують на те, що даний елемент опису може бути відсутнім. Як бачимо, заголовок функції завершується описом <типу результату>. Це тип того <значення>, яке функція формує додатково до можливих вихідних результатів, що передаються у точку її виклику через <! ВИХІДНІ параметрих Отож, останнім виконуваним оператором тіла функції є оператор присвоєння <значення> для сімені функції>. Цим значенням слугуватиме результат роботи функції або ознака успішності чи неуспішності результату виконання функцією алгоритму своєї роботи.
2. МОВА BORLAND PASCAL 125 Наприклад, необхібно написати функцію, яка обчислює дискримінант квадратного рівняння. Можливі два варіанти розв’язання цієї задачі: Function Dyskr (a, b, c : Real; Var D : Real) : Boolean; Var R ; Real; Begin R := S<gfr (b) - 4 * a * c; If R < 0 then Begin Dyskr := False; Exit End else Begin Dyskr := True; D := Sqrt (D) End End; У цьому варіанті функція Dyskr через своє ім’я передає логічне значення False, якщо дискримінант є від’ємним, і True, икщо - додатним. Значення дискримінанта передається через вихідний формальний параметр D. Інший варіант функції може набути такого вигляду: Function Dyskr (a, b, с : Real) : Real; Var R : Real; Begin R := Sqr (b) - 4 * a * c; If R < 0 then Begin Writeln ('Дискримінант від''ємний '); Writeln ('Натисніть будь-яку клавішу !'); Readln; Halt End else Dyskr := Sqrt (D) End; Тут значення дискримінанта передається за посередністю Імені функції. Якщо дискримінант виявиться від’ємним, функція видасть відповідне повідомлення, а потім процедурою Halt завершить роботу усієї програми.
126 2.7. Підпрограми Виклик функції на виконання відбувається так: Ім’я функції разом із фактичними параметрами записують у виразі, що стоїть у правій частині оператора присвоєння за правилами використання змінної в операторі. Наприклад, для нашого першого варіанту функції виклик набуде такого вигляду: Var Rez : Boolean; Begin Rez := Dyskr (a, b, c); If Rez <> True then Begin Writeln ('Дискримінант від''ємний '); WriteJLn ('Натисніть будь-яку клавішу !'); Readln; Halt End else Begin Для другого варіанту: Var Rez : Real; Begin Rez := Sqrt (Dyskr (a, b, c)); 2.8. Стандартні підпрограми Стандартні (вбудовані) підпрограми - це підпрограми, визначені відповідною версією мови Pascal. Оператори введення/виведення, оператори графіки та оператори роботи із рядковими даними є звертаннями до відповідних процедур за їхнім іменем. Єдина особливість полягає в тому, що ми наразі розглянули процедури без параметрів, а більшість убудованих процедур використовує параметри. Назвемо найважливіші стандартні процедури і функції, які використовують у ВР. їхній детальний опис можна знайти у Help середовища ВР. Стандартні процедури і функції визначено наперед.
2. MOB A BORLAND PASCAL Ul Функції перетворення Chr - повертає символ із заданим порядковим номером; Ord - повертає порядковий номер, що має значення порядкового типу; Round - заокруглює значення дійсного типу до значення типу Longlnt; Trunc - перетворює значення дійсного типу до значення типу Longlnt без заокруглення; Арифметичні функції Функція Заголовок функції Тип аргументу Результат роботи функції /Ш(х) Function Abs(x); Змінна або вираз дійсного чи цілого типу Модуль аргументу того ж типу, що й аргумент АгсТап(х) Function ArcTan (x. Extended). Extended; Змінна або вираз дійсного чи цілого типу Арктангенс аргументу Cos(x) Function Cos (x: Extended). Extended, Змінна чи вираз дійсного типу Косинус аргументу, який задано в радіанах Ехр(х) Function Exp (x: Real). Real; Змінна або вираз дійсного чи цілого типу Експонента (е*) - е=2.7182 - основа натурального логарифма Frac(x) Function Frac (x.Real): Real; Змінна чи вираз дійсного типу Дробова частина аргументу lnt(x) Function Int (x.Real): Real.; Змінна чи вираз дійсного типу Ціла частина аргументу Ln(x) Function Ln (x: Real). Real, Змінна чи вираз дійсного типу Натуральний логарифм (Ьп (е)= 1) Pi Function Pi: Extended.; тс = 3.1415926535897932385 Sin(x) Function Sin (x. Extended). Extended, Змінна чи вираз дійсного типу Синус аргументу, який задано в радіанах Sqr(x) Function Sqr (x: Extended): Extended; Змінна або вираз дійсного чи цілого типу Квадрат аргументу (X2) SqrKx) Function Sqrt (x: Extended): Extended; Змінна чи вираз дійсного типу Квадратний корінь (^) аргументу X1'= Exp(Y*Ln(x)).
128 2.8. Стандартні підпрограми Процедури порядкового типу Dec(\) Procedure Dec (Var x [;N:LongInt])\ Змінна або вираз перелічувального типу х := х -1; або х := х - Рї; Зменшує значення змінної Inc (х) Procedure Inc (Var x [;N:LongInt]); Змінна або вираз перелічувального типу X := х + 1; або х := х + Збільшує значення змінної Функції порядкового типу Odd - перевіряє, чи є аргумент непарним числом; Pred - повертає попереднє значення аргументу; Succ - повертає його наступне значення. Рядкові процедури Delete - видаляє підрядок з рядка; Insert - вставляє підрядок у рядок; Str - перетворює чисельне значення в його рядкове представлення; Val - перетворює рядкове значення в його чисельне представлення. Рядкові функції Concat - виконує конкатенацію (об’єднання) послідовності рядків; Copy - повертає підрядок з рядка; Length - повертає динамічну довжину рядка; Pos - робить пошук підрядка у рядку.
2. МОВА BORLAND PASCAL 129 2.9. Рекурсія Рекурсія (від латинського recursio - повернення) - спосіб організації обчислювального процесу, у якому процедура або функція, під час виконання операторів, які формують її тіло, звертається сама до себе. Щоб кількість таких самовикликів не стала нескінченною, у тексті підпрограми необхідно ввести перевірку умови, при виконанні якої подальші самовиклики припиняються. Щоб негайно припинити роботу рекурсивної підпрограми, необхідно вставити в неї оператор: If KeyPressed then Halt ; У мові Pascal немає жодних обмежень на рекурсивні виклики підпрограм. Треба тільки розуміти, що кожний черговий рекурсивний виклик спричинить до утворення нової копії локальних об’єктів підпрограми. Усі копії, що відповідають ланцюжку активованих і ще не завершених рекурсивних викликів, існують незалежно один від одного. Кожна копія займає певний об’єм пам’яті в області так званого стека. Коли стек переповниться, програма зупиниться і видасть повідомлення: Error 202: Stack overflow error. Рекурсія досить часто застосовується у програмуванні внаслідок рекурсивної природи багатьох математичних алгоритмів. Кожен рекурсивний алгоритм можна перетворити в еквівалентний ітераційний (на базі циклічних конструкцій). У великих і складних програмах іноді доводиться замінювати рекурсію на ітерацію. Річ у тому, що рекурсія передбачає багатократний виклик процедур, однак ефективніше використовувати цикли. Проте рекурсивні версії програм, зазвичай, значно коротші та елегантніші. Пояснення механізму рекурсії часто здійснюють на основі функції для обчислення факторіала натурального числа. N1 = 1*2*3*... *(N-2)*(N-1)*N; 1! = 1; 01 = 1. ft 7 461
130 2.9. Рекурсія Нерекурсивну (ітераційну) функцію для обчислення N! реалізують так: Function Factor (N : Integer) : Longlnt ; Var і : Integer ; {параметр циклу } ' Res : Longlnt ; {результат} Begin Res := 1 ; For і := 1 to N do Res := Res * і ; Factor := Res End ; Рекурсивна функція обчислення N! є дещо компактнішою. Вона заснована на співвідношенні: N! = (N-1)!*N. Тобто для отримання значення факторіалу числа N достатньо помножити на N значення факторіала від попереднього числа. Рекурсивну програму, яка обчислює факторіал числа, наведено нижче: Program Recurs_Factor; Uses Crt ; Var N : Integer ; F : Longlnt ; Function RecFactor (N : Integer) : Longlnt ; Begin * If N <= 1 then RecFactor := 1 else RecFactor := N * RecFactor (N - 1) End; BEGIN Write ('Введіть число N= 1) ; ReaUln (N) ; F := RecFactor (N) ; Writeln ('Для числа ', N, ' значення факторіала =',F); Repeat Until KeyPressed END. Після запуску програми і зчитування з клавіатури значення N активізується функція RecFactor з параметром-значенням N. У підпрограмі-функції перевіряється умова N <= 1. Якщо вона виконується, то функції RecFactor присвоюється значення 1. На цьому виконання підпрограми завершується.
2. МОВА BORLAND PASCAL 131 Якщо умова N <= 1 не справджується, то виконується обчислення добутку N * ИесЕасЬог (И - 1). Обчислення добутку відбувається рекурсивно, оскільки у. цьому випадку здійснюється виклик функції ИесЕас*Ьог (N - 1), значення якої обчислюється, відповідно, через виклик функції ііесЕас-Ьог, параметром якої слугуватиме функція КесЕас-Ъог і т. д. доти, доки значення формального параметра N не дорівнюватиме 1. Останнє повернення результату обчислення функції ИесЕасЪог присвоїть змінній Е значення добутку всіх чисел від 1 до Ы, тобто факторіал числа N. 2.9.1. Приклади програм з рекурсією 1. Знаходження N-то члена арифметичної прогресії. aN- а2 + d*(N - 1) - формула iV-ro члена арифметичної прогресії. Program ArifmProgr ; Uses Crt; Var al, d, k ; Real ; N ; Integer ; Function Arifm (al, d; Real; N; Integer): Real ; Begin If N = 1 then Arifm := al else Arifm := Arifm (al, d, N - 1)+ d End; BEGIN N := 10; Write ('Введіть перший член прогресії ') ; Readln (al) ; Write (’Введіть різницю арифметичної прогресії') ; Readln (d) ; Writeln ('Арифметична прогресія',Arifm(al, d, N):4:2); Repeat Until KeyPressed END. 2. Програма виводить на графічний екран задану нами з клавіатури кількість N різнокольорових вкладених квадратів, кожен наступний з яких будується шляхом розміщення його вершин на середині відповідних сторін попереднього квадрата.
132 2.9. Рекурсія Program Kvadraty; Uses Crt, Graph; Var x, y, xl, yl, x2, y2, x3, y3, n, d, Drv, Drm : Integer; Procedure Pic(x, y, xl, yl, x2, y2, x3, y3, n, d : Integer) ; Var k , j : Integer; Begin If n >=1 then Begin {Малюємо квадрат} MoveTo ( x, у ); LineTo ( xl, yl); LineTo ( x2, y2); LineTo ( x3, y3); LineTo { x, у ); {Обчислюємо координати сторін наступного квадрата } j := х; k := у; x := (xl-x) div 2 + х; у := (yl-y) div 2 + у/ xi := (х2-х1) div 2 + xl; yl := (y2-yl) div 2 + yl; x2 := (x3-x2) div 2 + x2; y2 := (y3-y2) div 2 + y2; x3 := (j-x3) div 2 + x3; y3 := (k-y3) div 2 + y3; SetColor {Random{14) + 1); {Випадковий вибір кольору сторін квадрата} Ріс (х, у, xl, уі, х2, у2, хЗ, уЗ, n-1, d) {Рекурсивний виклик} End End; BEGIN ClrScr; Write ('Введіть кількість вкладених квадратів '); Readln ( N ); х := 0; у := 0; xl := 400; yl := 0; х2 := 400; у2 := 400; хЗ := 0; уЗ := 400; Drv Detect; InitGraph ( Drv, Drm, 'c:\BP\BGI'); ClearDevice; SetBkColor ( White ); SetLineStyle [0, 0, 3); Pic (x, y, xl, yl, x2, y2, x3, y3, N, d) ; {Перший виклик процедури} Repeat Until KeyPressed END.
2. МОВА BORLAND PASCAL 133 3. Програма рекурсивної побудови дерева з гілок, послідовно розташованих з точки (х, у) відрізків, які поступово змінюють розмір Ь і напрям а. Uses Graph, Crt; Var Drv, Drm: Integer; Procedure Gilka (x, y, L: Integer; a: Double); Const b = Pi / 5/ { кут між гілками } M = 0.8/ {коефіцієнт покроковоі зміни розміру гілки} Var хО, уО : Integer; Begin Delay{3); If (L < 9) or ( L > 100) then { Обмеження діапазону розмірів гілки є умовою припинення рекурсії } Begin Setcolor (Magenta); Circle(x, у, 3)/ EXIT End; {Встановлення різних стилів для різних елементів рисунка } If L > 40 then Setcolor ( 6) If L < 30 then SetLineStyle (0,0,1) else SetLineStyle(0,0,3); Moveto (x,y); {перехід до стартової точки малювання } х0 := х; уО := у; {початок гілки} х := х + Round( L * Cos(a)); { координати кінця гілки} у:= у + Round ( L * Sin(а)); Lineto{x, у); { малюємо гілку } Gilka (х, у, Round (L * ш) , а - b / 2); { перша гілка - відхилена на кут -Ь/2 } Gilka (х, у, Round (L * ш) , а + b / 2); { друга гілка - відхилена на кут +Ь/2 } {повернення до попередніх координат перед початком нової ламаної} Moveto(хО, уО) BEGIN Drv:=Detect; InitGraph(Drv, Drm, f С:\BP\BGI1); Gilka(320, 480, 100, -Pi / 2); { передавання в процедуру параметрів базової гілки} SetFillStyle (4, Green); Bar (120, 470, 520, 480); Repeat Until KeyPressed; CloseGraph END. Program Derevo; else Setcolor(10); End;
134 2.9. Рекурсія 4. Рекурсивний метод половинного ділення. Program MpdJRecurs; { $N+} Uses Crt; Const Eps = 1.0e-14; Var a, b, c : Extended; depth : Word; Function F(x : Extended): Extended; Begin F := x * x - 4.0 End; Procedure Bisect( Var a, b : Extended); Begin If KeyPressed then Halt; Inc (depth)/ c := 0.5 * (a + b); If F(b) - F(a) < Eps then Exit; If F(c) >= 0.0 then b := c else a := c; Bisect(a, b) End; BEGIN depth := 0; a := 0.0; b := 5.0; Bisect(a, b); Clrlcr; Writeln ('Корінь р-ня F(x) =0 приблизно =', Writeln ('Глибина рекурсії ', depth) ; Repeat Until KeyPressed END. с: 10:3) ;
2. МОВА BORLAND PASCAL 135 2.10. Керуючі структури програми Кожна програма (чи підпрограма) складається з фіксованого набору базових конструкцій алгоритмічної мови. Головними конструкціями є: проходження, розгалуження, цикл. Застосовуючи тільки ці три конструкції, можна реалізувати алгоритм розв’язання будь-якої складної задачі. • Проходження - це конструкція, що є послідовним виконанням двох чи більше операторів. • Розгалуження - це конструкція, яка забезпечує, залежно від результату перевірки певної умови, виконання однієї або іншої послідовності операторів. У скороченому варіанті виконується чи не виконується (обходиться) всього один набір операторів. • Цикл - це вид керуючої структури, який дає змогу багато разів повторити задану послідовність операторів. Кожну з перелічених конструкцій можна розглядати як окремий оператор, оскільки вони мають єдиний вхід і єдиний вихід. Також довільну послідовність операторів можна розглядати як один складений оператор. 2.10.1. Оператор присвоювання := Тип змінної і тип виразу, згідно з якими обчислюється значення цієї змінної, повинні збігатися (окрім випадку, коли вираз належить до цілого типу, а змінна - до дійсного; у цьому випадку відбувається перетворення значення виразу до дійсного типу). 2.10.2. Оператор безумовного переходу вОТО Зазвичай, оператори у програмі виконуються в тому порядку, в якому їх описано. Оператор ЄОТО <мітка>; змінює природний порядок виконання програми і передбачає, що наступним виконуватиметься оператор, позначений міткою, яку вказано в операторі безумовного переходу. Позначений оператор
136 2.10. Керуючі структури програми можна розташувати у тексті програми як вище, так і нижче оператора ЄОТО. Приклад запису оператора переходу: ООТО 2; 2: а := Ь;. Починаючи з 1968 року, й до сьогодні тривають дискусії щодо шкідливості чи корисності цього оператора. Все почалось із тодішнього березневого номера журналу “Communications of the ASAT\ де відомий теоретик програмування Дейкстра оприлюднив свій висновок: якість програмного коду є обернено пропорційною до кількості операторів GOTO, які є у тексті програми. Згодом він стверджував, що значно легше довести коректність програми, якщо у ній зазначений оператор відсутній. Програму без GOTO легше оптимізувати, легше форматувати. Потім з’явились висновки інших авторів, які стверджували, що програма з GOTO працює швидше. У 1974 році Доналд Кнут навів приклади, які заперечували ці твердження. Десятиліття досліджень так і не змогли переконливо довести цілковиту непотрібність цього оператора. Сучасний теоретик, програмування Стів Макконел стверджує, що використовувати GOTO без крайньої потреби не варто, проте, за необхідності, можна - як крайній засіб для виходу із ситуації [61]. , 2.10.3. Умовні оператори (розгалуження) До умовних операторів зачислено два варіанти оператора If і оператор Case. Оператор If має дві форми запису: • скорочена форма. If <логічний вираз > then <набір операторів> /
2. МОВА BORLAND PASCAL 137 Цей оператор працює за правилом: якщо слогічний вираз> справджується (його значення дорівнює True), то виконується набір операторів (простий, чи складений), далі виконується оператор, що є наступним. Якщо ж цей вираз не справджується (його значення дорівнює False), то даний набір операторів оминається. ні If а > b then Begin і г {набір операторів } набір операторів End; Приклад скороченого умовного оператора • повна форма: Блок-схема скороченого умовного оператора If <лог±чний вираз> then <1-й набір операторів> else <2-й набір опера.торін> ; Наприклад: If а > b then Begin f1-й набір операторів} End else Begin {2-й набір операторів} End; Приклад повного умовного оператора Блок-схема повного умовного оператора
138 2.10. Керуючі структури програми Увага\ Оскільки структура If... then ...else формує один оператор, перед словом else символ не ставлять. Якщо його поставити, ми отримаємо скорочений оператор If і помилковий оператор, який розпочинатиметься словом else. Вкладені умовні оператори Зазначимо, що в умовному операторі If «Слогічний вїфаз> then <1-й набір опєратор1в> else <2-й набір операторів> ; у ролі <набору операторів> можна використовувати будь-які оператори, у тім числі й умовні. Це спричинює до вкладення умовних операторів за однією з наступних схем : If Слогічний вираз 1> then <1-й набір опера торі в> else if Слогічний вираз 2> then <2-й набір операторів> else <3-й набір опера торі в> ; або If Слогічний вираз 1> then if <логічний вираз 2> then <1-й набір операторів> else <2-й набір операторів> else <3-й набір операторів>/ або If *<логічний вираз 1> then if Слогічний вираз 2> then Cl-й набір операторів> else С2-Й набір операторів> else if Слогічний вираз 3> then СЗ-й набір операторів>; else С4-Й набір операторів> ; Щоб зрозуміти останню конструкцію, необхідно пам’ятати, що else завжди належить до найближчого передуючого йому if, У разі невизначеності, якої умови стосуються дії в конструкціях “then ... else”, варто використовувати операторні дужки Begin ... End (за аналогією зі звичайними дужками).
2. МОВА BORLAND PASCAL 139 Умовний оператор Case (оператор вибору) Якщо необхідно обрати для виконання один із декількох наборів операторів, яких є понад два, використовують оператор вибору Case. Його загальна форма запису: Case < перемикач > of сдіапазон вибору 1> : < Набір операторів 1 >; <діапазон вибору 2> : < Набір операторів 2 >; <діапазон вибору N> : < Набір операторів N >; else {оператори} End; Принцип роботи оператора Case: спочатку обчислюється значення виразу-перемикача. Якщо воно потрапляє у будь-який <діапазон вибору>, то виконується набір операторів, який відповідає цьому діапазону. Якщо ж це значення не належить жодному із діапазонів, виконуються оператори, розташовані після else. Можлива також скорочена форма запису оператора Case, у якої e/se-частина відсутня. Діапазонами вибору можуть слугувати константи скалярного, перелічувального та інтервального типів, причому типи констант- діапазонів і тип виразу-перемикача повинні збігатися. Приклад: Програма - калькулятор Program Calculate; {виконує арифметичні дії над дійсними числами } Uses Crt; Var Operation : Char; { Змінна, що міститиме знак операції} а, Ь, с : Real; {а, b - аргументи, с - результат } Stop : Boolean; { Змінна для закінчення роботи програми} BEGIN ClrScr; { Очищення вікна виводу результатів} Stop := False; { False - початкове значення змінної Stop} Repeat { Початок циклу з післяумовою } Write (' Введіть два дійсних числа а b = '); Readln (а, Ь); Writeln (' Введіть одну з операцій: + - * / ’);
140 2.10. Керуючі структури програми Write (• Або будь-яку літеру для виходу з програми' ) ; Readln ( Operation ) ; Case Operation of { Початок оператора вибору } '+*: с := а + Ь; ' -' : с : = а - b; 1 *': с := а * Ь; 1 /1 : с := а / b else Stop := True {Зміна значення змінної Stop на True } End ; {для закінчення роботи з калькулятором} If not Stop then Writeln (' Результат = 1, с) / Until Stop {Кінець циклу з післяумовою } END. 2.10.4. Цикли Комп’ютер, на відміну від людини, здатний безпомилково здійснити багаторазове виконання (цикл) одного оператора чи серії операторів. У цьому полягає одна із переваг комп’ютера як інструмента для полегшення розумової праці. Очевидно, що кількість цих повторень має бути скінченною і виконатись вони повинні за порівняно незначний проміжок часу, після завершення якого отримані результати обчислень будуть ще актуальними. Щоб запрограмувати цикл, необхідно передбачити: • змінну-параметр, що містить поточне значення деякої величини, яка зростає чи спадає за кожним витком циклу; • діапазон зміни значень параметра; • механізм і крок зміни цих значень; • Механізм контролю моменту виходу значення параметра за межі заданого діапазону з метою завершення роботи циклу. Доцільно, щоб, за необхідності, мова програмування забезпечувала можливість дострокового закінчення циклу з переходом на наступний після циклу оператор, або негайного закінчення роботи всієї програми, якщо подальше її продовження неможливе. Хоча всі перелічені вище пункти можна запрограмувати, використовуючи арифметичні оператори й оператори передачі
2. МОВА BORLAND PASCAL 141 управління І/ і СОТО, кожна з мов програмування високого рівня містить спеціальні оператори для організації подібних багато- Сіазових обчислень. Ці оператори називають операторами циклу, хнє коректне використання підвищує наочність та зрозумілість програми і полегшує її удосконалення. Якщо на момент початку багаторазового виконання потрібного фрагмента програми кількість його повторень відома, то використовують цикл із відомою кількістю повторень. В інших випадках застосовують так звані ітераційні цикли, яких у мові Рахсаі існує два види: цикл з передумовою і цикл з післяумовою. Кожен із перелічених видів циклу має свої особливості використання і специфічне коло задач, де його застосовувати найдоцільніше. Еог - ЦИКЛ ІЗ ВІДОМОЮ КІЛЬКІСТЮ повторень (з параметром) Цикл із параметром використовують у тих випадках, коли заздалегідь (до початку виконання циклу) можна визначити кількість повторень циклу N. Він слугує для організації ТУ-разового виконання тіла циклу для значень параметра циклу з деякої упорядкованої дискретної множини. Кожен оператор циклу налічує заголовок і тіло циклу. Є два варіанти циклу із відомою кількістю повторень: • параметр циклу зростає, починаючи від снижньої межі> до <верхньої межі>. Його записують так: Тог < параметр > := < нижня межа> to < верхня межа> сіо <*іло циклу>; • параметр циклу спадає, цикл набуває вигляду: Тог <параметр> : = сверхня межа> сісптЬо снижня межа> сіо <тіло циклу>; У наших позначеннях: <параметр> - змінна будь-якого скалярного типу, окрім дійсного, яка виконує роль лічильника кількості повторень циклу. Її
142 2.10. Керуючі структури програми ще називають параметром циклу, або індексом, або лічильником, Ця змінна є порядкового типу, тобто типу, на множині значень якого визначено поняття “попередній елемент” і “наступний елемент”. Найчастіше використовують змінні типу Integer (однак допустимі Char, Boolean та ін.); <нижня межа> Сверхня межа> - межі діапазону зміни лічильника. їх можна задавати як конкретні значення, так і з допомогою змінних чи виразів, тип яких збігається з типом змінної- параметра. Очевидно, що змінну-параметр і змінні-межі необхідно попередньо описати. Крок зміни параметра у першому випадку дорівнює і, у другому <тіло циклу> - це оператор, розташований за ключовим словом do. Якщо необхідно повторити декілька операторів, то їх беруть в операторні дужки Begin ... End, і тілом циклу стає складений оператор. Приклади: 1. For і := 1 to 100 do { заголовок циклу, у якому параметр і змінюється з кроком 1 від 1 до 10 0 }. 2. For j := 20 downto 10 do { заголовок циклу, у якому параметр j змінюється з кроком -1 від 20 до 10 }. 3. N := 10; М := 100; For k := N to К do { заголовок циклу, у якому межі задано за допомогою змінних N і М }. 4. For L := N + 1 to M * M do { заголовок циклу, у якому межі задано виразами} • Пояснимо роботу оператора циклу з параметром For на основі третього прикладу . N := 10; М := 100; For k := N to М do <тіло циклу>; Вона відбувається за таким алгоритмом: • параметрові циклу k присвоюють початкове значення N; • його порівнюють з кінцевим значенням М;
2. МОВА BORLAND PASCAL 143 • якщо в упорядкованій множині, до якої належать змінні k N М, k передує М чи збігається з ним, то виконується тіло циклу; • параметрові k присвоюють значення, наступне за тим, яке в нього було (тобто обчислюється значення функції Svlcc (k)); • нове значення k порівнюється з кінцевим значенням М; • якщо під час перевірки з’ясовують, що поточне значення k перевищило значення М, відбувається вихід з циклу - виконують наступний за тілом циклу оператор; • якщо значення k є меншим чи дорівнює М, виконання тіла циклу продовжується. Аналогічно пояснимо алгоритм роботи оператора For із параметром, значення якого спадає: N := 10; М ;= 100; For k ;= М down to N do <т±ло циклу >; • параметрові циклу k присвоюють початкове значення М; • його порівнюють з кінцевим значенням N; • якщо в упорядкованій множині, до якої належать змінні k N М, k передує М чи збігається з ним, то виконується тіло циклу; • параметрові k присвоюють значення, що передує тому, яке в нього було (тобто обчислюється значення функції Pred(k)); • нове значення k порівнюють з кінцевим значенням М; • якщо під час перевірки з’ясовують, що поточне значення k перевищило значення М, відбувається вихід з циклу - виконується наступний за тілом циклу оператор; • якщо значення k є більшим чи дорівнює М, виконання тіла циклу продовжується.
144 2.10. Керуючі структури програми Зауваження: 1. Цикл із параметром зручно використовувати у тих випадках, коли необхідну кількість повторень тіла циклу можна визначити заздалегідь. 2. Тіло циклу оператора For може не виконатися жодного разу. Це відбудеться, якщо в упорядкованій множині кінцеве значення параметра циклу передує початковому (у випадку to) чи початкове значення передує кінцевому (у випадку downto). Це відбувається тому, що перевірка умови виконуваності циклу For здійснюється перед початком виконанням циклу. Отож, цикл із параметром можна вважати частковим випадком циклу з передумовою While < умова> do, що розглядатимемо пізніше. 3. Параметр циклу не повинен змінюватися будь-яким оператором усередині циклу. Параметр може довільно використовуватися в операторах, які формують тіло циклу. Присвоєння йому нового значення усередині тіла циклу є недопустимим, оскільки це може спричинити до непередбачених наслідків. 4. Якщо ж Ви все-таки зміните значення параметра циклу в тілі циклу, то це у жодному випадку не вплине на кількість виконань тіла циклу, оскільки її визначено заздалегідь (перед входом у цикл) і при подальшій роботі вона не змінюється. 5. Параметр циклу, як і будь-яку іншу змінну, необхідно описати у розділі опису змінних. 6. Після виконання оператора циклу параметр циклу є невизначеним. Його не можна використовувати у наступних операторах без попереднього присвоєння йому нового значення. 7. Вхід у тіло циклу можливий тільки через його заголовок. У наших алгоритмах цикли зі скінченним числом повторень позначають трьома блоками (2, 4 і 5 на рис. 2.17 або рис. 2.18). Знак <- і зменшений розмір блоків 2 і 4 нагадує про те, що це не блоки арифметичних операторів.
2. МОВА BORLAND PASCAL 145 Рис. 2.17. Блок-схема циклу зі Рис. 2.18. Блок-схема циклу зі спадним зростаючим параметром параметром Приклад: Державний прапор України і сонце Ілюстраційна програма, яка демонструє дію оператора For. На графічному екрані малює Державний прапор України і сонце. Program Prapor; Uses Crt, Graph; Var Drv, Drm, і : Integer; {Опис змінних, і - параметр циклу } BEGIN Drv := Detect; { Перемикання екрана у } InitGraph (Drv, Drm, 1C:\BP\Bgi');{ графічний режим роботи } f. SetBkColor (White); {Колір фону - білий - } SetColor (Blue); {Колір ліній - блакитний } For і :=1 to 100 do {Цикл, що малює 101 J горизонтальну} Line (100, 100 + і, 350, 100 + і); { блакитну лінію зверху вниз } SetColor (Yellow); {Колір ліній і кіл - жовтий } * For і := 100 downto 1 do {Цикл, що малює 101 горизонтальну} Begin ( Line(100, 200+і,350,200+і);{жовту лінію знизу вгору і } % Circle (500,200,і); {101 жовте коло } Delay (2000) { Затримка кожного витка циклу на 2 с} End; { для наочності показу роботи циклу } f Repeat Until KeyPressed { Затримка показу результату роботи до моменту натискання будь-якої клавіші } END.
146 2.10. Керуючі структури програми Результат роботи програми: Цикл із передумовою While (доки) Цикл “доки” слугує для організації багаторазового виконання групи операторів (тіла циклу) доти, доки залишається вірним (True) значення логічного виразу, який міститься у його заголовку між словами While do. Цикл із передумовою має такий формат: While < логічний вираз > do і й > . ^ Ш < тіло циклу >; і Цикл “доки" використовують у тому випадку, коли необхідно, щоб спочатку перевірялася деяка умова, а потім (якщо умова справджується) виконувалися оператори, що формують тіло циклу. Зазначимо, що у тілі циклу обов’язковою є наявність оператора, ЯКИЙ ПОСТІЙНО ЗМІНЮЄ ЗНачеННЯ ЗМІННОЇ, яка ВХОДИТЬ у «логічний вираа> і значення якої перевіряється у цьому жирааі. Цикл завершить свою роботу, якщо ця змінна стане такою, що значення <логічкого вираау> зміниться з True на False. Після закінчення виконання циклу виконуватиметься перший оператор, розташований після оператора циклу. Якщо під час запису умови, яка формує «логічний жираз>, припустилися помилки, то в такій ситуації можливе зациклення - значення логічного виразу ніколи не становитиме False і, як наслідок, тіло циклу виконуватиметься “вічно”. У цьому випадку користувач змушений буде перервати роботу програми комбінацією клавіш Ctrl+Breai\ чи Ctr+Alt+Dek — при запуску програми в середовищі Windows.
2. МОВА BORLAND PASCAL 147 Блок-схема циклу з передумовою матиме вигляд: Тіло циклу Г 1 Рис. 2.19. Блок-схема циклу While Зауваження: 1. Тілом циклу може слугувати будь-який оператор, у тім числі складений. Це дає змогу циклічно повторювати не одну, а декілька дій. У цьому випадку конструкція циклу “доки” матиме вигляд: While <лог±чний вираз> do Begin <оператор 1>; <оператор N> End; 2. Якщо ж значенням <логічного виразу> під час першої перевірки слугуватиме False, тіло циклу не виконається жодного разу. 3. Дозволено використання вкладених циклів, тобто конструкцій, у яких деякі оператори тіла циклу самі можуть бути циклами. Приклад: While < логічний вираз 1 > do While < логічний вираз 2 > do Begin < оператор k > While < логічний вираз 3 > do < оператор N >; < оператор L > End;
148 2.10. Керуючі структури програми 4. Вхід у тіло циклу можливий тільки через його заголовок. Приклад використання оператора циклу з передумовою. { Обчислення суми ряду : 1 +1/2 +1/3 +1/4 +... + 1/N } Program DemoJHhile; Uses Crt; Var Sum : Real; і, N : Integer; BEGIN Write ( 1 Уведіть кількість членів ряду N= ' )/ Readln ( N ); і : = N / Sum := 0/ While і >= 1 do ;{ Begin Sum := Sum + 1 / і; і := і - 1 End; % Writeln ('Сума '/N,' членів ряду дорівнює ',Sum:10:3 ); Repeat Until KeyPressed END. Зазначимо, що точність обчислення суми у нашому випадку (тобто при підсумовуванні у зворотному порядку) є вищою, ніж при підсумовуванні у прямому внаслідок скінченності розрядної сітки комп’ютера. Отож, підсумовування впорядкованих послідовностей завжди доцільно здійснювати з того кінця, де елементи мають менше значення абсолютної величини. Цикл із післяумовою Repeat (доки не) В операторі циклу з післяумовою, який починається зі слова Repeat, а закінчується словом Until, багаторазово виконується послідовність операторів тіла циклу, розташованих між словами Repeat Until. Repeat Стіло циклу> Until Оіогічний вираз>; Результат обчислення логічного виразу є булівського типу. Оператори тіла циклу виконуються доти, доки результат виразу не
2. МОВА BORLAND PASCAL 149 набуде значення True. Тіло циклу завжди виконається принаймні один раз, оскільки обчислення значення <лог±чного виразу> здійснюється тільки після кожного виконання послідовності, що формує тіло циклу. Необхідно, щоб у логічний вираз, що керує повторним виконанням тіла циклу, входила змінна - параметр циклу, і щоб заміна її значення відбувалась усередині тіла циклу. Тоді цикл не продовжуватиметься безконечно. Процедури завчасного завершення циклу Для всіх операторів циклу вихід з тіла циклу може здійснюватись як унаслідок природного закінчення оператора циклу, так і за допомогою операторів примусового виходу. Для примусового виходу з циклу у Borland Pascal визначені стандартні процедури Break;, Continue; і Halt; . • процедура Break; припиняє виконання тіла циклу і виконує безумовний перехід на перший оператор, розташований після тіла циклу; • процедура Continue; забезпечує перехід до початку нового витка циклу; • процедура Halt; негайно припиняє роботу програми з переданням управління операційній системі. 2.11. Розв'язання нелінійних рівнянь Нехай необхідно розв’язати нелінійне рівняння /(*) = 0, (2.11.1) тобто знайти таке значення х, за якого рівняння (2.11.1) перетворюється на тотожність. Загалом це рівняння може мати безліч розв’язків. Множину значень змінної {х}, для якої рівняння (2.11.1) є тотожністю, називають розв’язком рівняння. Кожне значення х з цієї множини називають коренем цього рівняння. Методи, які ми розглядаємо, дають змогу знаходити один із коренів, який міститься на заданому інтервалі [я, Ь\. З погляду геометрії, корінь - це точка перетину графіка у - /(х) з віссю Ох . Загалом коренем є дійсне число, значення якого на цифровій ЕОМ
150 2.11, Розв’язання нелінійних рівнянь можемо визначити тільки наближено із наперед заданою нами точністю ЕрБ. Корінь х* називають простим, якщо /'(х*);*0, у протилежному випадку корінь називають кратним. Ціле число т є кратністю кореня х*, якщо /* (х*) * 0 для к = 1,2,З,..., т -1 і /"(XV 0. Постановка задачі обчислення наближеного значення коре- ял з точністю є : обчислити таке значення х, що |х - х*| < £ . Задача розв’язання рівняння (2.11.1) матиме два етапи: 1. Локалізація коренів, тобто визначення інтервалів на осі Ох, на кожному з яких існує тільки один корінь. Наближені межі цих інтервалів можна обчислити шляхом табулювання функції /(х). Довжину кроку табулювання підбирають інтуїтивно. За великого кроку є небезпека проскочити корінь. Надто малий крок значно збільшує трудомісткість процесу. 2. Обчислення із певною точністю кореня, розташованого на заданому інтервалі. Для розв’язання задачі локалізації коренів немає інших рекомендацій, окрім такого твердження: якщо на кінцях деякого інтервалу [а, Ь] функція /(х) має різні знаки (тобто /(я) * /(6) < 0 ), є неперервною і монотонною, (тобто /'(*) не ЗМІНЮЄ знак для всіх значень хє [а,6]), то на цьому інтервалі існує єдиний корінь рівняння (2.11.1). Під час розв’язання практичних задач часто інтервал [а, Ь\, що містить необхідний корінь, відомий досліднику заздалегідь. Локалізувати корені можна шляхом табулювання (з достатньо малим кроком) функції /(х) і виокремлення інтервалів, на яких значення функції змінює свій знак.
2. МОВА BORLAND PASCAL 151 2.11.1. Метод половинного ділення Рис. 2.20. Малий кут перетону половинного ділення графіком осі Ох Метод половинного ділення (МПД) - це універсальний метод чисельного розв’язання задачі (2.11.1). Він є хоч і повільний, проте завжди приводить до шуканого результату. Його у літературі ще називають “методом ділення відрізка навпіл”, або “методом бісекцій”, або “методом дихотомії”, або “методом вилки”. («/ Ось його «мисливська» інтерпретація: “Є завдання спіймати лева у пустелі. Як це зробити? Виявляється, дуже просто. Оточимо пустелю високим парканом. Перегородимо оточену ділянку навпіл і подивимось, де виявиться лев. Ту половину пустелі, де він бігає, перегородимо ще раз. Так діятимемо доти, доки лев не опиниться в коробці, розміром з величину лева”. Послідовність розв’язання задачі (2.11.1) методом половинного ділення: • Описуємо мовою Ра«са/-функцію /(х), що відповідає рівнянню (2.11.1). • Задаємо інтервал [а, Ь], на якому існує тільки один корінь рівняння, і бажану точність його обчислення Ера . За необхідності табулюємо /(х). • Перевіряємо, чи виконується умова: /(а) */(*)> 0, (2.11.2)
152 2.11. Розв’язання нелінійних рівнянь тобто чи шуканий корінь справді міститься всередині заданого інтервалу. • Якщо умова (2.11.2) не виконується, програма видає повідомлення про відсутність кореня на зазначеному інтервалі і пропонує ввести уточнені межі. • У випадку виконання умови (2.11.2) визначаємо середину інтервалу [а, Ь], тобто точку с - > і перевіряємо умову: №*№> о. (2.11.3) • Якщо вона виконується, то праву межу інтервалу Ь переносимо в середню точку с - шляхом присвоєння Ь\-с\. (див. рис. 2.19). У протилежному випадку в точку с переносимо ліву межу (а := с;). • Поділ уточненого інтервалу [а, Ь] навпіл і перенесення однієї із меж інтервалу продовжуємо доти, доки не виконається умова \Ь -а| < ЕрБ . • Друкуємо обчислене наближене значення кореня. 2.11.2. Особливі випадки МПД 1. Простота формули с = ~~~ зовсім не означає її оптималь- ності з погляду точності обчислень. Пояснимо сказане на простому прикладі. Нехай процесор гіпотетичної ЕОМ забезпечує точність обчислень з трьома знаками після коми. Нам відомо, що корінь деякого рівняння знаходиться на інтервалі [0.596,0.6]. Обчислимо середину цього інтервалу на цій трирозрядній машині: а + Ь = 0.596 + 0.6 = 1.196. Отримали чотирирозрядний результат, який буде заокруглено до 1.2. Тоді с = 1.2/2 = 0.6, що збігається із правою межею заданого інтервалу. Очевидно, що розв’язати задачу не вдасться. Виберемо трохи складнішу формулу для визначення середини інтервалу:
2. МОВА BORLAND PASCAL 153 Одержимо с = 0.596 + 0.004/2 = 0.598, що є правильним результатом. З погляду швидкодії найліпшим є такий запис нашої формули: с = а+0.5-ф-а). 2. Спробуємо розв’язати з допомогою МПД рівняння х2 - 4= 0 . Оберемо межі інтервалу локалізації кореня [1,3]. Під час першого поділу цього інтервалу навпіл ми натрапимо на корінь. Проте перевірка умови (2.11.2) не передбачає завершення процесу пошуку кореня. Алгоритм продовжуватиме пошук кореня і, в кращому випадку, знайде його за чималу кількість поділів, а у гіршому випадку - спричинить до хибного результату. Заміна в умові (2.11.2) знака > на знак > також проблему не вирішить. В арифметиці з плаваючою комою точний результат поділу вдається отримати надто рідко. Проте вихід із цієї ситуації існує: до перевірки умови (2.11.3) зробити ще одну перевірку: |/(с)| < Ерв . її виконання засвідчує, що точка с розташована поблизу шуканого кореня (в межах заданої точності) і її значення необхідно надрукувати як шуканий корінь. 3. Аналогічно необхідно перевіряти, чи одна з меж інтервалу локалізації кореня, тобто а чи Ь, не збігається (в межах заданої точності) з коренем, тобто чи не справджуються умови |/(а)| < і |/№)| < ЕрБ. У випадку їхнього виконання ділити відрізок навпіл не варто. Корінь уже знайдено. Зауваження. Перевірку умов типу \/{с)\<Ер$ можна здійснювати, якщо графік функції у-/(х) перетинає вісь Ох під великим кутом. Якщо цей кут є досить малим, корінь можна обчислити з надто великою похибкою (рис. 2.20). Головною перевагою методу половинного ділення є простота його реалізації та надійність. Якщо інтервал [а, 6] містить корінь, алгоритм його знайде із заданою точністю. Недоліком можна вважати невисоку швидкість збіжності методу та неможливість безпосереднього узагальнення для розв’язання систем нелінійних рівнянь.
154 2.11. Розв’язання нелінійних рівнянь 2.11.3. Алгоритм МПД Рис. 2.21. Блок-схема алгоритму МПД
2. МОВА BORLAND PASCAL 155 2.11.4. Програма МПД Program XI0_MPD; {Навчальна проп^рама (див. рис. 2.21)} Uses Crt ; {Підключення стандартного модуля Crt } Label 1 ; Var Eps,a,b,c,Fa,Fb,Fc: Real;{Eps - Точність обчислень a b —> Межі локалізації кореня; c -* Середина інтервалу [а, b]; Fa Fb Fc -» Значення функції в точках а b с} Lich : Integer; { Lich -> Лічильник повторень) Function f (х : Real) : Real ; Begin f := x * x - 4 { Рівняння x2-4 = 0 } End; BEGIN {Початок головної програми } Lich := 0; {Занулення лічильника спроб вводу даних} ClrScr; { Очищення екрана} Repeat {Повторення введення значень a b Eps, доки не виконаються умови, які задано у виразі Until (див. нижче)} Write ('Введіть коректні межі а Ь і точність Eps=f); Readln (a, b, Eps) ; { Введення з клавіатури a b Eps} Fa := f(а) ; Fb := f (b) ; If Abs (Fa) <= Eps then { Чи ліва межа інтервалу а - корінь ?} Begin с := а ; Goto 1 End else If Abs (Fb) <= Eps then { Чи права межа інтервалу b - корінь ?} Begin с := b ; Goto 1 End ; If Lich > 2 then { Чи вичерпана максимальна кількість (2) спроб введення початкових умов ?} Begin Writeln (’Дротабулюйте функцію. Good Bye !'); Readln ; Exit { Закінчення роботи і вихід з програми } End ; Lich := Lich +1; { Збільшення лічильника спроб введення даних} Until ( b > а ) and ( Fa * Fb < 0 ) and ( Eps > 0 ) ;
156 2.11. Розв’язання нелінійних рівнянь Lich := 0; { Занулення лічильника поділу інтервалу [а, Ь] навпіл } While (b-a) > Eps do {Цикл поділу інтервалу [а,Ь] пополам} Begin с := а + 0.5*(b - а) ; Lich := Lich +1; {Збільшення лічильника поділу інтервалу [а,Ь] } Fc := f(с); If Abs (Fc) < Eps then Goto 1 ; {Чи середина інтервалу с - корінь ?} If Fa * Fc > 0 then Begin Fa := Fc ; a := c End else b: =c End; c := a + 0.5 * (b-a) ; 1: Writeln (1 Знайдено корінь x=1, c:10:3 ,'sa N=', Lich, ' поділів') ; Writeln ('Точність Eps=',Eps); Repeat Until KeyPressed {Затримання показу вікна Output} END. 2.11.5. Метод Ньютона для розв'язання нелінійних рівнянь Ще одним популярним методом рішення задачі щодо обчислення кореня рівняння (2.11.1), що належить заданому відрізку [а, b] із точністю є , € метод Ньютона (дотичних). Задамо деяке початкове наближення х0 є [а, Ь] і лінеаризуємо функцію -fix) воколі х0 за допомогою частини ряду Тейлора: /(*) = /(*ь)+/Ч*<>И*-*ь). ' Замість рівняння (2.11.1) розв’яжемо лінеаризоване рівняння /(*„) + /,(х0)-(л:_л:о) = Оі трактуючи його розв’язок х як перше наближення до кореня х] - х0 - / (J=b) Продовжуючи цей процес т раз, приходимо до формули Ньютона:
2. МОВА BORLAND PASCAL 157 /(де ) 4»+i (2.11.4) яка є ітераційним процесом . • з ітераційною функцією /(*) /'(*)' Геометричну інтерпретацію цього процесу проілюстровано на рис. 2.22. Рівняння (2.11.4) є рівнянням прямої, дотичної до кривої /(де) у точці дс0, отож, цей метод називають методом дотичних. ,ї(х) = X — Рис. 2.22. Геометричне трактування методу Ньютона (дотичних) Головною характеристикою ітераційного процесу є його збіжність. Збіжність методу Ньютона оцінюється нерівністю \хт+1-х,\<\хт-х'\2де М2=тах\/"(х)\, щ=2тіп\/'(х)\, х є [а, Ь\. Таку збіжність називають квадратичною, оскільки похибка кожного кроку обчислень є пропорційна до квадрату попередньої.
158 2.11. Розв’язання нелінійних рівнянь Рис. 2.23. Метод збігається Рис. 2.24. Метод не збігається Зазначимо, що поліпшення збіжності методу Ньютона, порівняно з іншими методами, досягається збільшенням витрат на виконання кожного кроку, оскільки на кожному кроці треба обчислювати не тільки значення функції /(*), але й значення її похідної /'(*) • Щоб позбутися необхідності обчислювати похідну на кожному кроці, використовують модифікований метод Ньютона, у якому похідну обчислюють тільки один раз: <2Л1Ї) Цей метод можна також вважати методом релаксацій із параметром г = -1//'(*0) • Збіжність методу є лінійною. Можна довести, що початкове наближення .v0 для початку ітераційного процесу необхідно вибирати таким, щоб виконувалась умова f(x0)* f'(x0)>0. В іншому випадку ітерації методу Ньютона можуть і не збігатись до розв’язку.
2. МОВ А BORLЛNDPЛSCAL 159 2.11.6. Алгоритм методу Ньютона Якщо локалізовано проміжок [<а, Ь\, на якому розташований корінь рівняння (2.11.1), його уточнюємо алгоритмом Ньютона, який програмуємо так: В описовій частині програми описуємо: 1. Три Ра5са/-функції дійсного типу від аргументу де з іменами /, /р і /2р, які, для заданого значення де, визначають, відповідно, значення функції, її першу та другу похідні. 2. Змінні дійсного типу: а, і, точність обчислення кореня Ерз, робочі змінні де, Их. 3. Змінні цілого типу: і - параметр циклу; Ктах - максимально допустиму кількість ітерацій. У виконуваній частині програми: 1. Вводимо межі а, Ь проміжку локалізації кореня, значенння точності Ерй та кількості ітерацій Ктах. 2. Надаємо змінній де значення Ь. 3. Якщо/(х)*/2р(х)>0- переходимо до п. 8, якщо ні, то: 4. Надаємо змінній де значення а . 5. Якщо Дх) */2р(х)>0 - переходимо до п. 8, якщо ні, то: 6. Виводимо на екран повідомлення: “Для заданого рівняння збіжність методу Ньютона не гарантується” 7. Переходимо до п. 8. 8. Починаємо цикл по і від 1 до Ктах, у якому: a) обчислюємо Вх= /(х)//р(х); b) виконуємо ітерацію Ньютона: х = х - Ох; c) якщо АЬяфх) > Еря - продовжуємо виконувати цей ітераційний цикл, якщо - ні, то:
160 2.11. Розв’язання нелінійних рівнянь I. виводимо на екран шукане наближене значення кореня де; II. завершуємо роботу програми. 9. У випадку успішного завершення цього циклу виводимо на екран повідомлення: ”3а задану кількість ітерацій корінь з точністю Eps не знайдено”. 10. Завершуємо роботу програми. Примітка: Значення виразів для першої та другої похідних можна обчислити “вручну” за правилами математичного аналізу. Програма буде універсальнішою, якщо похідні знаходити чисельно. Першу похідну визначають: • за означенням похідної: fp(x) =(f(x + Dx) - f(x)) I Dx . Другу похідну визначають одним із двох способів: • аналогічно до першої: f2p(x) =(fp(x + Dx) - fp(x)) / Dx. • за чисельною триточковою формулою: f2p(x) =(f(x + Dx) +f(x - Dx) - 2*f(x)) / Dx2 . Значення Dx доцільно вибирати таким: Dx = Eps 11000.0. Після кожного оператора виведення на екран повідомлень чи результату необхідно затримувати зображення екрана, наприклад, оператором Repeat Until KeyPressed;. Тестовий приклад: f(x) = Зх- 4 Ln(x) -5 = 0. Межі локалізації кореня: [2,4\. Наближене значення кореня: 3.23. Завдання для самостійної роботи Запрограмувати та дослідити на прикладах метод Ньютона згідно з алгоритмом, який наведено вище.
2. МОВА BORLAND PASCAL 161 трапеція додатною: то 2.12. Обчислення визначених інтегралів 2.12.1. Площа криволінійної фігури Нехай функція /(х) є неперервна і не змінює знака на інтервалі [а, Ь]. Плоску фігуру Ф, обмежену графіком функції /(х), віссю абсцис і прямими х = а та х = Ь, називають криволінійною трапецією. Із шкільної геометрії кожному знайоме поняття площі фігури Б(Ф). Відомо, що площа володіє такими властивостями: • площа будь-якої фігури є величиною Б(Ф)>0 ; • рівні фігури мають рівні площі: якщо Ф, =Ф2 , 8(Ф,) = 8(Ф2); • площа фігури дорівнює сумі площ її частин. У кожну криволінійну фігуру можна вписати множину рівних маленьких квадратів, що не перекриваються і цілком лежать усередині фігури Ф. Нехай сума їхніх площ дорівнює а,. Аналогічно можна побудувати іншу множину квадратів, яка цілковито покриває фігуру Ф. Позначимо суму їхніх площ 5,. Очевидно, що я, < 5,. Можна довести, що криволінійна трапеція невід’ємної функції /(х), яка є неперервною на інтервалі [а, Ь\, має площу 8(Ф) , що задовольняє нерівність 5( < 8(Ф) <5, , причому 5, і 5, прямують до 8(Ф) за необмеженого зменшення площі кожного квадрата. Ця границя 8(Ф) не залежить від способу поділу фігури Ф на квадрати (рис. 2.26). / \ ХІ \ е JL V ) N / Рис. 2.26. Площа криволінійної фігури 6 7-451
162 2.12. Обчислення визначених інтегралів 2.12.2. Визначений інтеграл Розглянемо неперервну і невід’ємну на інтервалі [а, Ь] функцію /(х) . Поділимо інтервал [а, Ь] на N відрізків точками х0,х],...,хи . Проведемо через ці точки прямі, перпендикулярні до осі абсцис. Тоді криволінійна трапеція Ф, що відповідає графіку функції у - /(х), поділиться на N частин, кожна з яких також є криволінійною трапецією. Позначимо Ахі - хі - хі_1 , х0 = а , Хм=ь І оберемо ДОВІЛЬНО ТОЧКИ Є Добуток АХі'/(%і) є площею прямокутника, обмеженого віссю абсцис, прямими х = , х = хі і горизонтальною прямою у = //£■/. Сумарна площа східчастої фігури, що є об’єднанням усіх прямокутників, N дорівнюватиме сг, = ^/(^ )Ахі . і=і Площа залежатиме від вибору кількості прямокутників N і точок £ . При достатньо дрібному розбитті ця східчаста фігура мало відрізнятиметься від початкової фігури Ф у тому сенсі, що N можна довести існування границі 5= Ііт 'У\/(4і)Ьхі, яку вважають рівною площі криволінійної трапеції Ф. Число J називають визначеним інтегралом від функції /(х) на інтервалі [а, Ь], якщо для будь-якого є > 0 існує таке N є N , що для розбиття інтервалу [а, Ь] на рівні частини N точками і для будь-якого вибору ТОЧОК £ е[х._гх] ^виконується N < є. Зазначимо, що у цьому визначенні нерівність І=1 передбачається, що функція /(х) може бути як додатною, так і від’ємною. Якщо число J існує, то функцію /(х) називають інтегрованою на інтервалі [а, Ь]. Визначений інтеграл позначають ь |/7х)гіх . Числа а і Ь називають межами інтегрування. Граничне
2. МОВА BORLAND PASCAL 163 N значення S = lim y'f(gi)Ax, називають інтегралом Рімана від ow функції f(x). Леопард Ейлер Жозеф Лагранж ОгюстінКоші (1707-1783) (1736-1813) (1789-1857) Рис. 2.27. Творці інтегрального числення Готфрід Лейбниць (1646-1716) Яків Бернулі (1654—1705) Іоган Бернулі Коротка історична довідка Знак J запропоновано у 1675 р. німецьким математиком і фізиком Готфрідом Лейбницем. Цей символ є деформованою латинською літерою S - першою літерою слова Summa. Термін інтеграл запропонував у 1690 році швейцарський математик Яків Бернулі у своїй публікації стосовно розв ’язання задачі про ізохрону. Слово походить від латинського integro, яке означає приводити в попередній стан, відновлювати, оскільки операція інтегрування “відновлює” функцію, похідною якої є підінтегральна функція. Назву нової галузі математики - інтегральне числення (<calculus integralis) у 1696 році запропонував Іоган Бернулі, молодший брат Якова Бернулі. Строге визначення інтеграла як границі суми подав у 1823 році французький математик і фізик Огюстін Коші. Інші загальновідомі терміни, що належать до інтегрального числення, виникли пізніше. Назва первісна функція (вживають сьогодні) замінила попередню - “примітивна функція”, яку ввів у 1797 році французький математик і механік Жозеф Луї Лагранж. Латинське слово primitivus
164 2.12. Обчислення визначених інтегралів перекладається як “початковий”. Функція Р(х) = |/(х)сЬс - початкова (або первісна) для функції /(х), яку отримують з Р(х) шляхом диференціювання. У сучасній літературі множину всіх первісних для функції / (х) називають також невизначеним інтегралом. Це поняття запровадив Лейбниць, який помітив, що всі первісні функції відрізняються на довільну сталу. ь Позначення ^/(х)сіх - визначений інтеграл ввів Жан Батист Фур’є а (1768-1830% а межі інтегрування почав зазначати Леонард Ейлер. 2.12.3. Методи чисельного інтегрування У фізиці інтеграли використовують з метою визначення роботи; визначення моменту інерції тіла; визначення шляху, який пройшло тіло за законом зміни його швидкості та ін. Отож, геометричне тлумачення визначеного інтеграла від ь невід’ємної функції |/(х)с!х - це площа криволінійної трапеції, а обмежена знизу віссю Ох, зверху - графіком функції /(х), а з боків; - прямими х = а і X = Ь . Безліч інтегралів на практиці неможливо виразити через елементарні фунщії (наприклад, [5Ш^ сіх), Отож, на допомогу * х приходить обчислювальна техніка. Зокрема, чисельне розв’язання слугує єдиним виходом, коли підінтегральну функцію задано таблично. / Суть, більшості методів чисельного інтегрування полягає у заміні підінтегральної функції /(х) іншою функцією (р(х), для якої можна легше записати первісну у вигляді елементарних ь ь функцій. Тобто |/(х)<іх -1 ер(х)йх+/?=5 + /?. Тут змінною 5 а а позначено наближене значення шуканого інтеграла, а через Л - похибку обчислення цього інтеграла.
2. МОВА BORLAND PASCAL 165 Залежно від способу вибору апроксимуючої функції ср(х) методи чисельного знаходження визначених інтегралів умовно поділяють на такі групи [70]: 1. Методи Ньютона-Котеса.. Для чисельного інтегрування тут у ролі апроксимуючої функції використовують поліноми різних степенів. У випадку полінома нульового степеня метод чисельного інтегрування називають методом прямокутників; у випадку полінома першої степені - методом трапецій; у випадку полінома другої степені - методом парабол {Сімгісона). Усі ці методи є частковими випадками квадратурних формул Ньютона- Котеса. Степінь апроксимуючого полінома впливає на кількість вузлів, у яких необхідно обчислити значення функції /(х). Методи цієї групи є найпростішими для реалізації. 2. Сплайнові методи. Функцію /(х) апроксимують відрізками поліномів однакового степеня (сплайнами). Методи розрізняють за степенями поліномів. 3. Методи найвищої алгебричної точності {типу Гауса- Кристофеля). Використовуються алгоритми, які, для заданої кількості вузлів забезпечують мінімальну похибку інтегрування шляхом оптимального вибору відстані між кожною парою суміжних вузлів. Методи цього класу розрізняють за способом вибору вузлів. Це є найуживаніша група методів, незважаючи на вищу складність їхньої реалізації порівняно з методами Ньютона-Котеса. 4. Методи Монте-Карло {імовірнісні методи). Тут вузли вибирають з допомогою генератора випадкових чисел. Методи є низькоточними, проте широко застосовуються при обчисленні кратних інтегралів. 5. Спеціальні методи. їх будують з урахуванням особливостей підінтегральних функцій з погляду зменшення часу та похибки обчислень. У кожному методі із перелічених груп обчислюють наближене значення визначеного інтеграла 5 й оцінюють похибку обчислень Я . Спочатку, при збільшенні числа поділів N інтервалу інтегрування [а, Ь], внаслідок зростання точності апроксимування функції /(х), похибка Я зменшуватиметься. Щодо цього без-
166 2.12. Обчислення визначених інтегралів перервно зростає похибка, яка існує завдяки наближеному сумуванню часткових інтегралів. Починаючи з деякого числа розбивань И0пт, ця частина похибки стає переважаючою і загальна похибка Я починає зростати (рис. 2.28). Виведемо формули і розглянемо принципи числового обчислення визначених інтегралів з групи методів Ньютона- Котеса. чисельного інтегрування 2.12.4. Методи прямокутників Це найпростіші методи із зазначеної групи. Тут підінтег- ральну функцію на кожному проміжку апроксимують сталою у = С (поліномом 0-ої степені). Оскільки сталу можна вибирати на графіку функції в будь-якій точці і -го проміжку, то така заміна є неоднозначною. Наближене значення інтеграла визначається як площа прямокутника, одна зі сторін якого є довжиною відрізка хі+/ ] > а друга - апроксимуюча константа С . Розрізняють метод лівих, метод правих та метод центральних прямокутників (рис. 2.29). № ЛСі Метод лівих прямокутників Метод правих прямокутників Рис. 2.29. Методи прямокутників Метод центральних прямокутників
2. МОВА BORLAND PASCAL 167 Можна довести, що методи лівих і правих прямокутників мають порівняно високу похибку. Найточнішим є метод центральних прямокутників, коли константу Є вибрати рівною /(х{+^), тобто в середній точці елементарного інтервалу інтегрування (рис. 2.30). У Рис. 2.30. Ілюстрація формули центральних прямокутників Для центральних прямокутників інтеграл на елементарному інтервалі [я,, хг+/] набуде вигляду: *і+1 $ f(x)dx=hf(x) + R, (2.12.1) ДЄ X Х( + Н / 2, Л ^точ. ^наближ. Для всього проміжку інтегрування площа криволінійної трапеції чи інтеграл за методом центральних прямокутників дорівнюватиме: (х)<іх = Іі^/(хі+^-) + К\ (2.12.2) і=1 де h = Ъ-а N-l Щоб оцінити похибку К , розкладемо підінтегральну функцію у ряд Тейлора в околі середньої точки х :
168 2.12. Обчислення визначених інтегралів Дх) = Дх) + /\х) + І£-рІ/'(х) +... (2.12.3) У малому околі точки х цей ряд з високою точністю представляє функцію /(х) за незначної кількості членів розкладу. Підставляючи під ійтеграл замість /(х) її тейлорівський розклад (2.9.3) та інтегруючи його почленно, можна обчислити інтеграл з наперед заданою точністю: При інтегруванні і підстановці границь отримаємо, що всі інтеграли від членів ряду (2.12.3), які містять непарні степені (х-х), перетворюються в 0. Порівнюючи співвідношення (2.12.1) і (2.12.4), можна записати вираз для похибки Я. За малого кроку інтегрування к основний вклад в похибку Я вносить перша складова розкладу (2.12.4), яку називають головною складовою похибки Яці обчислення інтеграла на інтервалі [х., х.+л]: Головний член для повної похибки в інтервалі інтегрування [х0, Хдг] загалом визначають шляхом сумування похибок на кожному частковому інтервалі [х,, хі+И]: До останнього інтеграла ми прийшли, використовуючи формулу центральних прямокутників для функції /"(х). Формула (2.12.6) - це теоретична оцінка похибок обчислення інтеграла методом центральних прямокутників. Ця оцінка є апріорною, оскільки не вимагає знання інтеграла, який обчислюється. Оцінка (2.12.6) не є зручною для практичного розрахунку похибок, але є корисною для вияснення структури головного члена похибки. Степінь кроку И, якій пропорційна величина Я, (2.12.4) (2.12.5) (2.12.6)
2. МОВ А BORLAND PASCAL 169 називають порядком точності методу інтегрування. Метод центральних прямокутників має 2-й порядок. Примітка. Якщо функція /(х) визначається з експерименту у дискретному числі вузлів, то метод центральних прямокутників застосувати неможливо, оскільки немає значень /(дг) в середніх точках. У цьому випадку застосовують інші методи Ньютона- Котеса. 2.12.5. Апостеорні оцінки похибок за Рунге та Ейткеном Апріорну оцінку похибки (2.12.6) можна записати так: В0=Акр , (2.12.7) де А - коефіцієнт, який залежить від методу інтегрування, а також від виду підінтегральної функції; р - порядок методу. Залежності (2.12.7) відповідає головний член похибки більшості методів чисельного інтегрування. При чисельному диференціюванні похибку також оцінюють за формулою (2.12.7). У цьому випадку порядок р залежатиме від кількості вузлових точок. Нехай обчислюється значення деякої змінної м? з кроком И. Тоді: и> = м>Н+АИР +0(}гр+1), (2.12.8) де »м/1?а Акр - головний член похибки; о{}гр+х) - нескінченно мала величина порядку Ир+1. Обчислимо ту саму змінну з кроком кИ: К = мки+ А(кИ)р + о(кк)р+1, (2.12.9) де к може бути як більшим, так і меншим за 1. Коефіцієнт А у виразах (2.12.8) і (2.12.9) буде однаковим, оскільки обчислюється одна і та сама змінна одним і тим же методом, а від величини к значення А не залежить. Нехтуючи безконечно малими величинами, прирівнюємо праві частини співвідношень (2.12.8) і (2.12.9). Враховуючи (2.12.7), отримуємо: +і?0 = \\>кЬ +крЯ0. Звідси:
170 2.12. Обчислення визначених інтегралів Формула (2.12.10) - це формула Рунге [43], яка дає змогу шляхом подвійного перерахунку величини з кроком к і кк оцінити похибку. Оскільки оцінювання виконують після обчислень, його вважають апостеорним. Формула (2.12.10) має велике значення, оскільки дає змогу здійснити оцінювання похибки без зміни алгоритму обчислювального процесу. При зменшенні к головний член похибки Яд прямуватиме до повної похибки Я . Після визначення Я0 можна обчислити уточнене значення шуканої величини: Це є друга формула Рунге. На жаль, похибка уточненого значення є невизначеною, хоча вона менша за Я0 . Формули Рунге є справедливими для всіх обчислювальних процесів, для яких виконується степеневий закон (2.12.7). З метою визначення р треба здійснити апріорне оцінювання похибки, що не завжди легко виконати. Англійський математик Ейткен запропонував спосіб визначення похибки для випадку, коли порядок методу р є невідомим. До того ж, алгоритм Ейткена дає змогу дослідним шляхом визначити р. Для цього потрібно втретє обчислити значення величини з кроком к2к . Тобто м/ = +А(к2И)р або % Прирівнюючи (2.12.9) і (2.12.12), отримаємо: - wk■2Л = ії$кр{кр -1) . Підставляючи сюди Л0 із першої формули Рунге (2.12.10), визначимо: ^ Отриманий вираз (2.9.13) разом з першою формулою Рунге (2.9.10) дає змогу оцінити похибку при виконанні обчислень методу із невідомим р. Більше того, логарифмуючи формулу (2.9.13) зліва і справа, отримаємо: ™уточ=™Ь+К0 • (2.12.11) ™ = м,кЧ+к2РКо ■ (2.12.12) (2.12.13) (2.12.14)
2. МОВА BORLAND PASCAL 171 Щодо обраного обчислювального процесу алгоритм Ейткена достатньо застосувати тільки один раз з метою визначення порядку методу, а потім використовувати формулу Рунге, котра вимагає лише двократного обчислення шуканої величини. Формулу (2.12.10) можна використовувати для тестування програм, які реалізовують чисельні методи з відомою апріорною похибкою. Апріорний та апостеріорний порядки для правильних програм збігатимуться. Зазвичай, вони збігатимуться наближено, оскільки в алгоритмах Рунге та Ейткена враховано лише головні члени похибок. 2.12.6. Метод трапецій Поділимо інтервал [а, Ь\ на N рівних частин. Пронумеруємо точки поділу одним із двох способів так, як це проілюстровано нарис. 2.31. Оберемо спочатку перший спосіб нумерування. Ь-а N-1 Рис. 2.31. Ілюстрація формули трапецій Нехай N = 5, тоді відстань між точками поділу к = Площа криволінійної трапеції становитиме: кЛ^±Л^+кЛ^іЛ^1^(/(а)+2/(Х!)+ . 2Г(х!)+2/(х4)+/(Ь»^^(/(а)*/(Ь>+2^/(хІ». 2 і=2 Узагальнюючи формулу на будь-яке N, отримаємо формулу методу трапецій:
172 2.12. Обчислення визначених інтегралів } /(х)ск = -(/(а) + Г(Ь) + 2£ Г(х,)) + я. (2.12.15) а 2 і-2 Якщо нумерувати вузли розбиття інтервалу [а, Ь], починаючи з 0, то формула трапецій частково зміниться. Позначаючи , Ь-а п = ■ , отримаємо: \ /(х)Ос = -(/(а) + ДЬ) + 2% /(х,)) + Я (2.12.16) а 2 і=1 Для методу трапецій головний член похибки на кроці становитиме: Я0,= ^/4(*,). (2.12.17) 12 ? Для відрізка [х0, х^] повну похибку отримаємо шляхом сумування часткових похибок (2.12.17): /і2 у ^0 =—]Ґ(4)^. (2.12.18) ■*0 Метод трапецій має похибку в 2 рази більшу за модулем порівняно з методом середніх прямокутників, хоча апроксимацію /(х) здійснено поліномом першого, а не нульового степеня. Очевидно, обраний'варіант апроксимації /(х), графік якої проходить через кінці [х„ хі+1\, не є оптимальним. Задачу вибору способу апроксимації поліномом заданої с^гепені з найменшою можливою похибкою розв’язано Гаусом, що спричинило до побудови класу методів Гауса-Кристофеля. 2.12.7, Метод парабол (Сімпсона) Розділимо інтервал інтегрування на N рівних підінтервалів. На кожному з них замінимо підінтегральну функцію /(х) інтерполяційним поліномом 2-го степеня (параболою), яка проходить через вузли у о з У\ ? У 2 (Рис- 2.32). Рівняння параболи
2. МОВА BORLAND PASCAL 173 у = ах2 +Ьх + с. Обчислимо площу цього підінтервалу, знайшовши визначений інтеграл на проміжку [-к, К\: й 3 2 7 Ь3 5= \(ах2 +Ьх + с)<к = (а^ + Ь^ + сх)^_ь==?^- + 2сІі. (2.12.19) Введемо позначення такі, як на рис. 2.32. Виразимо заштриховану площу через величини К У0, У\, Уі: ► X Рис. 2.32. До виведення формули у0 =ah -bh + c; Уі=с; у2 = ah2 +bh + c . Звідси, враховуючи, що yj=c, обчислимо а : 1 а = - 2к -(Уо~2у,+у2)- Підставимо знайдені значення коефіцієнтів а і с у вираз для площі нашого підінтервалу: 5 = Ц-~(у0-2уІ + у2) + 2ку1=-з(у0 + 4уІ + у2). (2.12.20) Це площа елементарної ділянки [-/>, К\. Для всього інтервалу [а, Ь] шуканий інтеграл обчислюватимемо так: Ь-а розділимо [а, Ь] на N — 2М рівних частин довжиною А = 2М Тобто [а = х0, хІУ х2, ... ,х2М_2, х2М_х, х2м =Ь] . Цим точкам розбиття (вузлам) відповідають значення функції Уо> Уі> У2>->У2М-2> У2М-1> У2М’ ДЄ >>/=/(ЧЛ а
174 2.12. Обчислення визначених інтегралів х* h jf(x)dx=— (у2 + 4у3 +у4). Просумуємо усі елементарні площі. З ь h Отримаємо: Jf(x)dx= ~(у0 + 4у1 + 2у2 +4у3 + 2у4+... +у2М) = а р. М М-1 = 1Jf(a) + f(b) + 4fjf(x2i_I) + 2'£f(x2i)). і 1=1 І—1 Це шукана формула парабол (Сімпсона): ь , М М-1 1/(х)^^(/(а)+/(Ь)+4^/(Х2,.,)+2^/(х2І)) (2Л221) а 5 і-1 М Якщо вживати позначення h = x2-x0= xj+J - xt_t, h = -——, M одержимо наступний вираз для формули Сімпсона: Ь . м-1 h М-1 \f(x)dx=-(f(a) + f(b)+4YJf(x2i + -) + 2YJf(x2i)) . (2.12.22) а 0 1=0 2 і=1 Похибка методу Сімпсона: = Ж J fUV)^)dx (2.12.23) 2.12.8. Програмування методів обчислення визначених інтегралів Зазначимо, що в основу кожного із трьох розглянутих нами методів покладено обчислення суми значень функції f(x) для різних значень аргументу х та різнрх кількостей членів суми. Доцільно оформити алгоритм обчислення суми як окрему функцію. У цьому випадку зможемо запрограмувати обчислення кожного із розглянутих інтегралів як окрему формули, що продемонстровано у програмі, наведеній нижче. Program XIO_Integral; Uses Crt; Var a, b, h, Int_p, Int_t, Int_S : Real; N, і : Integer; Function f (x : Real) : Real; Begin f := x * Sin (x)
2. МОВА BORLAND PASCAL 175 End; Function Sum (m : Integer; x : Real) : Real; Var і : Integer; s : Real; Begin s := 0; For і := 1 to m do Begin s := s + f (x) ; x := x + h End; Sum := s End; BEGIN Writeln (1 Введіть межі інтегрування a b та кількість поділів N ’); Readln (a, b, N); h := (b - а) / N; Int_p := h * Sum (N, a + h / 2); Int_t := h*0.5*(f(a) + f(b) + 2 * Sum (N - 1, a + h))/ Int_S := h*(f(a) + f(b) + 2 * Sum (N - 1, a + h) + 4 * Sum (N, a + h / 2))/6; Writeln ('Прямокутники=', Int_p)/ Writeln (’Трапеції= Int_t); Writeln (’Сімпсона= Int_S); Repeat Until KeyPressed END. 2.12.9. Обчислення інтегралів із заданою точністю Для перевірки співвідношень (2.12.6), (2.12.18), (2.12.23) запрограмуємо такий алгоритм обчислення визначених інтегралів: • Сформуємо описову частину програми аналогічно до попередньої програми XIO_Integral. • У виконуваній частині програми введемо, окрім значень а, b, N, ще точність обчислення інтегралів Eps. • Додатково введемо ознаку Met обраного методу: 1 - прямокутників; 2 - трапецій; 3 - Сімпсона. Програма обчислюватиме інтеграл із заданою точністю Eps лише одним методом, який ми обрали. Вибір методу зробимо з допомогою оператора Case Met of. • Для незначної кількості N поділів інтервалу [а, Ь]. обчислимо визначений інтеграл обраним нами методом і запишемо його значення у змінну Int_N.
176 2.12. Обчислення визначених інтегралів • Запустимо цикл з післяумовою, у якому: - збільшимо значення N на мале число (наприклад, 1); - перерахуємо значення кроку И з новим значенням N; - запишемо значення змінної Int Ny змінну Int_0; - обчислимо інтеграл обраним нами методом для нового значення кроку И і запишемо його у змінну Int_N; - цикл повторюватимемо доти, доки не виконається умова І Int __N -Int _0\< Eps. • Виводимо на дисплей обчислене значення шуканого інтеграла. • Завершуємо роботу програми. 2.12.10. Програма обчислення інтегралів із заданою точністю Program XI 0_lntegral_Tochn ; Uses Crt; Var a, b, h, lnt_0, Int__N, Eps : Real; N, Met, і : Integer; Function f (x : Real) : Real; Begin f := 1 / (1 + x + Sqr (x)) : End; Function Sum (m : Integer; x : Real) : Real; Var і : Integer; s : Real; Begin s : = 0 / For і := 1 to m do Begin s := s + f (x) ; x := x + h End; Sum := s; ^ End; BEGIN Writeln ('Введіть межі інтегрування: a b, кількість поділів N, точність Eps ')/ ReadIn (a, b, N, Eps); h := (b - a) / N; Write ('Введіть ознаку, Met : 1 - прямокутників; 2 - трапецій; 3 - Сімпсона.'); Readln ( Met);
2. МОВА BORLAND PASCAL 111 Case Met of 1: Int_N := h*Sum (N, a + h / 2); 2: Int_N := h*0.5*(f(a) + f(b) + 2 * Sum(N - 1, a + h)); 3: Int_N := h*(f (a) + f (b) +,2 * Sum (N - 1, a + h) '+ 4 * Sum (N, a + h /2))/6 End; Repeat N := N + 1/ h : = (b - a) / N; lnt_0 := Int_N; Case Met of 1: Int_N := h*Sum (N, a + h / 2); 2: Int__N := h*0.5*(f(a) + f(b) + 2 * Sum(N - 1, a + h) ) ; 3: Int_N := h*(f (a) + f (b) + 2 * Sum (N - 1, a + h) + 4 * Sum (N, a + h / 2)) /6 End; Until Abs (Int_N - lnt_0) < Eps ; Writeln ('Шуканий інтеграл =f, Int_N, 1 N=', N); Writeln ('Його точне значення =', Pi / (3 * Sqrt (3))); Repeat Until KeyPressed END. 2.12.11. Метод Монте-Карло © Розглянемо спочатку задачу-жарт: як за допомогою купи камінців (дуже малого об’єму) визначити Sk - площу калюжі, розташованої посеред прямокутної земельної ділянки (рис. 2.33), що має довжину L, а ширину М? Розв’язок. Нехай маємо камінців дуже багато, наприклад, N=30 000. Рівномірно закидатимемо камінцями всю площу нашої ділянки. Тоді при попаданні чергового камінця в калюжу, почуємо “бульк”, а при попаданні камінця на землю - “гуп”. Підраховуємо N6 кількість “бульків”. Витративши всі N камінців, легко знайдемо площу калюжі. Загальна площа ділянки S = L * А/буде так співвідноситись до площі калюжі, як кількість камінців N до N6: S N ' Звідси SK=S^~. (2.12.24) Задачу розв’язано.
178 2.12. Обчислення визначених інтегралів Рис. 2.33. Визначення площі калюжі На цьому принципі грунтується метод Монте-Карло ь обчислення визначених інтегралів І = |/(х)(іх , де а, Ь - нижня а і верхня границя інтегрування, а /(х) - неперервна функція, яка на інтервалі [а, Ь\ набуває тільки додатних значень (рис. 2.34). ІУ Рис. 2.34. Площа криволінійної трапеції Метод вперше запропоновано американським математиком Джоиом * Фон Нейманом при розв’язанні задачі моделювання нейтронної дифузії в матеріалі, який розщеплюється. Від його результату залежав успіх у створенні атомної бомби. Аналітичними методами виконати дослідження виявилось неможливо, а експериментальні дослідження були занадто тривалими і небезпечними. У методі Монте-Карло застосовано імовірнісні методи, які застосовували азартні гравці в рулетку у “столиці” ігрового бізнесу - місті Монте-Карло, розташованому у князівстві Монако. З погляду математики кулька рулетки є генератором випадкових чисел. Епоха комп’ютерів дає змогу програмно генерувати випадкові числа, що
2. МОВА BORLAND РЛБСАЬ 179 спричинило до розвитку чисельних методів, які використовують пипадкові числа для розв’язання задач. Ці ідеї ще у 30-х роках мстосовував, працюючи в Римському університеті, фізик Енріко Фермі. Нехай у нас є генератор випадкових чисел. Тоді для обчислення інтеграла використовуємо наступний алгоритм: 1. Табулюємо функцію /(х) на проміжку [а, Ь], визначаючи в процесі табулювання максимальне значення функції М на цьому проміжку. 2. Встановлюємо N6 = 0- початкове значення лічильника. 3. Обчислюємо 5 - площу прямокутника, сторони якого утворені віссю Ох, лінією у-М і двома вертикальними лініями: х = а і х = Ь (рис. 2.34): £ = (Ь - а) М. 4. Генеруємо на проміжку [а, Ь] N випадкових точок: х^а + и^Ь-а) ,де 0<£/;.<1, і = 1..К. 5. Для кожної точки хі генеруємо випадкове число У -17, ‘М і визначаємо значення у{ = f{xi). 6. Якщо У <Уі, значення N5 збільшуємо на одиницю: Иб = N6+1. 7. Завершуємо процес генерування випадкових чисел. Обчислюємо шукане значення визначеного інтеграла за методом Монте-Карло: Перелічимо головні переваги методу Монте-Карло: • Алгоритм легко узагальнюється на випадок обчислення кратних інтегралів для складних областей у багатовимірних просторах. • Похибка обчислень інтеграла не залежить від гладкості та неперервності функції /(х). Функція може бути і перервною. Головним недоліком алгоритму є його невисока точність і мала швидкодія. Проте для багатократних інтегралів швидкодія методі Монте-Карло (порівняно з методами, які ми розглядали (2.12.25) а
180 2.12. Обчислення визначених інтегралів раніше) різко зростає. Швидкодію можна також підвищити, якщо використовувати не рівномірний розподіл випадкових чисел, а згущувати кількість випадкових точок у підобластях найшвидшої зміни функції. 2 .12 .12 . Програма методу Монте-Карло Program XIO_Monte_Carlo; Uses Crt; Var a, b, h, x, у , M, Spr, S : Real; N, i, Nb : Integer; {N - Кількість точок табулювання f(x)} {Nb - Кількість "бульків" - потраплянь нижче графіка f(x) } Function f( х : Peal ) : Real; Begin f := 1 / (l+x+ Sqr (x)) { Підінтегральна функція } End; BEGIN Writeln ( 'Input a b N' ); ReadLn ( a, b, N ); h := ( b - a ) / N; x: = a; M := 0; {Табулюємо функцію і визначаємо її максимум на інтервалі [а,Ь] } For і := 1 to N do Begin у := f (х); If у > М then М := у; х := х + h End; Spr := ( b - а ) * M; Randomize; {Ініціюємо генератор випадкових чисел} Nb := 0; ь For і :=ь1 to 30000 do { Цикл методу Монте-Карло } Begin х := а + (b - а) * Random; Y := М * Random; If у < f(х) then Nb := Nb + 1 End; S := Spr * Nb / N; Writeln ( 'S=' , S ); ^ Repeat Until KeyPressed END.
2. МОВА BORLAND PASCAL 181 2.13. Масиви (Array) Масив - це великий простір дечого однорідного за типом [91]. Якщо необхідно запрограмувати обробку значної кількості даних однакового типу, то використання для цього елементів мови, які розглянуто до цього часу, є нераціональним або й зовсім неможливим. Наприклад, якщо необхідно написати програму, яка визначатиме середню температуру повітря за місяць, то нам довелося б описати 31 змінну, яка відповідала б значенням температури для кожного дня місяця. Щоб побудувати на екрані комп’ютера графік аналітичної функції у = f(x), необхідно обчислити таблицю значень х, у. Перед виведенням графіка на екран цю таблицю зберігають у пам’яті комп’ютера з метою масштабування значень і перетворення їх з дійсного типу у цілочисельний. Для розв’язання системи лінійних алгебричних рівнянь великого порядку її коефіцієнти доцільно записати у двовимірну квадратну таблицю - матрицю, а праву частину - в одновимірну таблицю - вектор. Присвоювати кожному елементові кожної таблиці своє унікальне ім’я складно і не варто. Наведені приклади доводять необхідність мати у мові програмування механізм опису таблиць, який забезпечуватиме доступ до всіх елементів таблиці за одним узагальненим іменем, присвоєним цій таблиці. Елементи таблиці у цьому випадку необхідно впорядкувати, тобто пронумерувати. Таку можливість у мові ВР надає структура даних, яку називають масив (Array). Масив - це обмежена впорядкована сукупність однотипних пронумерованих величин. Кожну окрему величину називають компонентою (елементом) масиву. Номери елементів називають індексами. Тип компонентів, який називають базовим типом, може бути будь-яким із допустимих у мові Pascal, окрім файлового типу. Іншими словами: масив - це структурована змінна, утворена послідовністю простих змінних, причому:
182 2.13. Масиви • усі компоненти {елементи) масиву мають один і той самий тип; • кожна компонента має свій номер (іІндекс) у послідовності і тим відрізняється від інших елементів (ідентифікується); • множина індексів є скінченною, зафіксованою в описі масиву, і в процесі виконання програми не змінюється; • можливість обробки компоненти (її доступність) не залежить від місця компоненти у послідовності (елементи масиву є рівнодоступні). Разсаі, завдяки індексам, забезпечує прямий доступ до кожного елемента масиву (крім прямого доступу ще буває послідовний доступ). Масиви, зазвичай, використовують у тих програмах, де потрібно зберігати під час виконання програми в пам’яті ЕОМ деяку сукупність величин одного типу. Уся сукупність компонентів визначається одним іменем, яке їй надає програміст згідно з правилами побудови імен, прийнятими у мові ВР. Для позначення окремих компонентів використовують конструкцію, яку називають змінною з індексом (чи з індексами). Наприклад'. В[3] А [5:, 2] Хе [ 12 3 ]. Індексом може слугувати виконуваний вираз допустимого для індексів типу, а саме: тільки інтервальний чи перелічувальний. Дійсні типи тут є неприпустимими. Індекси інтервального типу, для якого базовим є цілий тип, можуть набувати від’ємних, нульових і додатних значень. Щоб коректно використовувати масиви у Лі5са/-програмі, необхідно опанувати правила: • опису масиву; • заповнення його елементів значеннями; • використання масивів в арифметичних виразах; • використання масивів під час пересилання їхніх значень через формальні параметри у підпрограми.
2. МОВА BORLAND PASCAL 183 2.13.1. Опис масивів Описати масив можна двома 'способами. Перший спосіб опису масивів менш універсальний, другий - універсальніший. Спосіб М 1. В описовій частині програми після ключового слова Var пишемо: Var <ім'я>: Array [<вимірність, діапазон зміни індексів>] of <тип елементів>; • Ім’я масиву доцільно вибирати смисловим, за правилами побудови ідентифікаторів. • Вимірність масиву характеризує його структуру. Мова Pascal передбачає опис і використання як одновимірних (рядки чи стовпці), так і багатовимірних масивів. У математиці одновимірні масиви називають векторами, двовимірні - матрицями; у фізиці багатовимірні масиви називають тензорами. Двовимірні масиви зберігаються в оперативній пам’яті порядково. Роботу з масивами вищої розмірності за другу ми не розглядатимо. • Діапазон зміни індексів по кожному виміру масиву можна задати з допомогою або діапазонного типу: 1..4, або використати назву простого стандартного типу Byte. • Тип елементів може налічувати усі цілочисельні типи, усі дійсні типи і символьний тип Char, або відповідати деякому нестандартному типу, який увів програміст в описовій частині своєї програми з допомогою ключового слова Туре. Приклади описів різних масивів: Var Vec : Array [ 0. . 4 0 ] of Real Matr : Array [ 0. . 4, 1. . 3 ] of Integer; Tabl : Array [Byte] of Longlnt; Masyv : Array [0..128] of Char; Tab_l : Array [0..9] of Word; Tab_2 : Array [1..10] of Word; Два останні описи мають однакову довжину та однаковий тип елементів, проте різні діапазони зміни індексів. Зовсім не обов’язково у рядку опису масиву задавати явно діапазон зміни його індексів. Pascal передбачає і таку форму опису: Const N = 20; Var Vect : Array [0..N] of Real ;
184 2.13. Масиви Примітка: у мові Pascal для опису масивів із символів використовують іншу форму: stroka : string [12];. Це опис текстового масиву (рядка символів), який містить 12 елементів. Якщо написати: Stroka : String; , то компілятор виділить текстовий рядок довжиною 128 символів. За необхідності описати декілька масивів однієї структури і типу, їхні імена можна записати через кому. Наприклад: Var Ye, Yg : Array [0..640] of Real; {опис двох векторів}. «1,1 «1,2 «1,3 «1,4 «2,1 «2,2 й2,3 «2,4 «3,1 «3,2 «3,3 «3,4 «4,1 «4,2 «4,3 «4,4 У двовимірному масиві перший індекс визначає номер рядка, другий - номер стовпця. Тобто запис а [2,3] означає, що ми використовуємо елемент, розташований на перетині другого рядка і третього стовпця матриці. Спосіб М 2. Використовує механізм створення нестандартних (власних) типів даних: Type Vector = Array [0..640] of Real; Matflx = Array [0.. 4, 1..3] of Integer; Var Xe, Ye, Xg, Yg ; Vector ; L, U ; Matrix; Використовуючи ключове слово Type, ми спочатку створили два власні типи даних: • одновимірний масив (Vector) елементів дійсного типу кількістю 641; • двовимірний масив (Matrix) елементів цілого типу кількістю 5*3=15 штук. ^ Після цього у розділі Var описали чотири одновимірних і два двовимірних масиви потрібної нам структури. Цей спосіб опису масивій необхідно використовувати завжди, коли доводиться передавати значення елементів масиву у підпрограму через механізм формальних і фактичних параметрів.
2. МОВА BORLAND PASCAL 185 Примітка: Зверніть увагу на те, що перед ключовим словом Array у другому способі опису стоїть символ “=” , а в першому - символ В операторній частині програми всі значення одного масиву можуть бути присвоєні іншому, якщо їхні типи ідентичні. Наприклад, описані вище масиви можна переприсвоїти так: Хд := Хе; . 2.13.2. Заповнення елементів масиву значеннями Ініціалізація масивів Ініціалізацію або присвоєння початкових значень усім компонентам масивів можна здійснити двома способами. Перший спосіб - з використанням типованих констант, наприклад: Type Vec = Array [1..10] of Real; Const Ye: Vec = (0,2.1,4,5.65,6.1,6.7,7>2,8,8.7,9.3); При компілюванні другого рядка нашого прикладу ВР не тільки зарезервує для масиву Ye десять шестибайтних (Real) комірок, але й заповнить їх значеннями, поданими у круглих дужках. При ініціалізації двовимірних масивів значення компонент кожного з одновимірних масивів, які входять у нього, записується в дужках: Type Matr = Array [1..З,1..2] of Integer; Const A: Matr = ((1, 2) (3, 4) (5, 6)); Другий спосіб ініціалізації - використання різновиду процедури FillChar. FillChar ( Var V; NBytes: Word; В: Byte ); Ця процедура заповнює ділянку пам’яті однобайтовим значенням. Наприклад, для занулення масиву: А : Array [1..10] of Real; можна записати: FillChar ( А, 40, 0); ,ЧИ FillChar ( A, SizeOf (А) , 0); .
186 2.13. Масиви Уведення даних з клавіатури У найпростішому випадку значення Ne елементів одно- вимірного масиву Хе можна ввести, використовуючи цикл з відомою кількістю повторень: For і := 1 to Ne do Readln ( Хе[і] ); Введення елементів прямокутної матриці А, яка містить N рядків та м стовпців, можна здійснити, застосовуючи два вкладені цикли: For і := 1 to ^ do For j := 1 to М do Readln( A [ і, j] ); Якщо у першому випадку можна, напруживши увагу, ввести незначну кількість елементів, то ввести безпомилково елементи матриці, яка має кількість елементів більше за (5*5), є досить важко. Доцільно введення масивів організовувати з використанням тектових підказок, наприклад, так: Writeln ('Введіть елементи вектора Хе '); For і:= 1 to Ne do ♦ Begin write ('Xe[', i, ']='); Readln( Xe[i] ) End; Введення двовимірного масиву найліпше запрограмувати з використанням процедури GoToXY (х, Y);, яка належить до стандартного модуля Crt. Нагадаємо, що ця процедура дає змогу позиціонувати курсор текстового екрана у точку з координатами (х, Y). Якщо запрограмувати переміщення курсора у вузли уявної прямокутної таблиці на екрані, то введення матриці стає зручним і наочним. Аналогічно можна здійснити виведення на текстовий екран елементів матриці. ^
2. МОВА BORLAND PASCAL 187 2.13.3. Програма введення/виведення елементів матриці Program Хіо_Іnput_Output_Matrix ; Uses Crt; Type Matrix = Array [1..10, 1..10] of Real; Var A : Matrix; і, K, j, L, N: Integer; BEGIN ClrScr; GotoXY (5, 2); Write ('Введіть розмір матриці N= ') ; Readln (N); GotoXY (5,4); Write ('Вводьте елементи матриці'); L := 5; { Змінна L відповідає за рух курсора вниз } For і := 1 to N do Begin К :=1; {Змінна К відповідає за рух курсора праворуч } For j := 1 to N do Begin GotoXT (k, L); Write (' A[1 , i, ', ', j, ’] = '); Read (A[i, j] ) ; K := K + 16 End; L := L + 1 End; GotoXY (5, 13); Write ('Ви ввели таку матрицю'); L := 15; For і := 1 to N do Begin k := 1; For j : = 1 to N do Begin GotoXY (k, L); Write ('A[\ i, ’, ’, j, A[i, j ] : 6:1) ; K := k + 16 Ehd; L := L + 1 End; Repeat Until KeyPressed END.
188 2.13. Масиви Результат роботи цієї програми наведено нижче: Введіть розмір матриці 4 Вводьте елементи матриці А[1,1]=1 А[1,2]=2 А[1,3]=3 А[1,4]=4 А[2,1]=5 А[2,2]=6 А[2,3]=7 А[2,4]=8 А[3,1]=9 А[3,2]=10 А[3,3]=11 А[3,4]=12 А[4,1]=13 А[4,2]=14 А[4,3]=15 А[4,4]=16 Ви ввели таку матрицю А[1,1]= 1.0 А[1,2]= 2.0 А[1,3]= 3.0 А[1,4]= 4.0 А[2,1]= 5.0 А[2,2]= 6.0 А[2,3]= 7.0 А[2,4]= 8.0 А[ЗД]= 9.0 А[3,2]= 10.0 А[3,3]= 11.0 А[3,4]= 12.0 А[4Д]= 13.0 А[4?2]= 14.0 А[4,3]= 15.0 А[4?4]= 16.0 2.14, Налагодження програм засобами середовища ВР Інтегроване середовище (ШЕ) Вогіапсі Разсаі надає програмісту кілька технологій для полегшення процесу розробки програм: автоматичне управління проектами, засоби забезпечення модульної структури, програми, швидке компілювання та ін. Оскільки помилятися людям властиво, новостворена програма спочатку може містити помилки, які не даватимуть змоги їй коректно працювати. Завдання" полягає у якнайшвидшому виявленні і виправленні програмних помилок. У жодному випадку не можна відкладати пошук імовірних помилок на потім. Після написання програми необхідно уважно проаналізувати написаний текст з метою цілковитого усвідомлення алгоритму його роботи. Варто пояснити алгоритм ще комусь. Доцільно також вставити в текст програми тимчасові оператори виведення проміжних результатів. Це значно спростить процес налагодження. ШЕ ВР містить потужні інструментальні засоби налагодження програм, які полегшуватимуть процес пошуку помилок. Розглянемо ці засоби і поняття, які тут використано. Налагодження - це процес пошуку і виправлення помилок, які перешкоджають коректній роботі програми. Розрізняють такі головні типи програмних помилок: • помилки етапу компілювання^
2. МОВА BORLAND PASCAL 189 • помилки етапу виконання; • логічні помилки. Помилки етапу компілювання (синтаксичні помилки) фіксуються компілятором, якщо у тексті програми є оператори, у яких порушено правила синтаксису мови Pascal. ВР починає компілювати програму тільки після виправлення всіх синтаксичних помилок. Коли компілятор натрапляє на оператор, який він не може розпізнати, відповідний помилковий фрагмент програми виводиться у вікні редагування, курсор встановлюється на помилковий оператор і виводиться повідомлення про помилку. У цьому випадку компілятор повідомляє тільки про перший помилковий оператор, на який він натрапив. Узагальненою причиною синтаксичних помилок є механічні неточності набору тексту програми, пропущені крапки з комою, використання неописаних змінних, передача невірного числа (чи типу) параметрів процедури або функції і присвоювання змінній значення невідповідного їй типу. Тільки після успішного виправлення всіх синтаксичних помилок компілювання програми виконається і можна переходити до пошуку помилок двох інших типів, якщо такі, звичайно, є. Інформація щодо наявності помилок етапу виконання (семантичних помилок) з’являється тоді, коли прокомпільована і запущена на виконання програма робить щось неприпустиме. Це означає, що вона містить синтаксично правильні оператори мови Pascal, але під час виконання частина її операторів не працює за нашим алгоритмом. Наприклад, програма намагається відкрити для введення неіснуючий файл чи виконати ділення на нуль. У цьому випадку її виконання аварійно завершується з виведенням такого повідомлення: Run-time error ## at seg:ofs , де ## - номер помилки у списку помилок, seg: of s - логічна адреса машинної команди, яка спробувала виконати некоректну дію. Якщо програма виконується під управлінням IDE, ВР автоматично знаходить оператор, що спричинив помилку (як у випадку синтаксичних помилок). Якщо використовується компілятора командного рядка, то для пошуку помилки необхідно використати параметр /F. За умови виникнення помилки програму,
190 2.14. Налагодження програм засобами середовища ВР яку розробляють, можна запустити під управлінням IDE. Для відшукання помилкового оператора використовують команду текстового меню Search\Find Error, яка дає адресу помилкової команди як сегмента і зміщення (seg: of s). Логічні помилки - це помилки проектування та реалізації програми, яка містить синтаксично правильні оператори, які роблять щось непередбачене алгоритмом. Іноді причина цього є досить очевидною, і помилковий фрагмент програми можна швидко виправити. Проте трапляються незрозумілі помилки, зумовлені неправильною взаємодією різних частин програми. Подібні помилки спричиняють до некоректного значення змінних, неправильного виду графічних зображень чи невиконання очікуваного фрагмента програми. Тоді на допомогу приходить Debug - вбудований налагоджу- вач IDE. Він дає змогу зупинити процес виконання програми у підозрілому місці, пройти її крок за кроком і переглянути поточні значення змінних і виразів. Таке кероване виконання є ключовим елементом налагодження. Відстежуючи результат виконання кожного оператора, можна визначити, яка частина програми спричиняє проблеми. У Debug передбачено п’ять головних механізмів управління виконанням програми, що дає змогу: • здійснювати покрокове виконання операторів; • трасувати оператори; • виконувати програму до заданої точки зупинки; • знаходити визначену точку у програмі; • виконувати скидання процесу налагодження програми. Саме покрокове виконання програми може бути недостатньо корисним, хіба що допоможе знайти те місце, де щось працює неправильно. Кероване виконання дає змогу перевірити стан програми і її даних, наприклад, відстежувати поточний стан змінних програми. Розглянемо це детально. При налагодженні програми найменшим виконуваним елементом слугує її рядок. Це означає, що керувати налагодженням можна тільки до рівня окремого рядка вихідного тексту програми. Якщо в одному рядку програми міститься декілька операторів мови Pascal, налагоджувати їх окремо не можна. З іншого боку, з метою налагодження можна розділити оператор на декілька рядків, які виконуватимуться за одйн крок.
2. МОВА BORLAND PASCAL 191 Виконуючи рядок, Debug зразу повідомляє, який рядок виконуватиметься наступним. Цей рядок виокремлюється іншим кольором, ніж головний, що дає змогу відстежувати процес налагодження. Команди налагодження розташовані у таких трьох пунктах текстового меню редактора: Option, Run і Debug. 2.14.1. Генерування налагоджувальної інформації Перед налагодженням програми потрібно повідомити компіляторові про необхідність генерування деякої додаткової інформації, завдяки якій він зможе відстежувати, які рядки вихідного коду відповідають окремим частинам виконуваної програми. Цю додаткову інформацію називають налагоджувальною інформацією. Її вводять шляхом вибору відповідного параметра (кнопки з незалежним фіксуванням) у діалоговому вікні з назвою Compiler Options (рис. 2.35), що активізується командою текстового меню Options\Compiler, чи шляхом долучення до тексту програми відповідної директиви компілятора. Рис. 2.35. Діалогове вікно Compiler Options У процесі компілювання нашої програми компілятор ВР завжди зберігає список імен усіх її змінних, констант, типів, процедур і функцій, який називають таблицею ідентифікаторів. Для цілей налагодження там зберігаються також номери рядків
192 2.14. Налагодження програм засобами середовища ВР вихідних файлів з текстами підпрограм, які налічують усі ці ідентифікатори. Вибір у діалоговому вікні Compiler Options параметра Debug Information, чи використання директиви {$D+} повідомляє компілятору, що в таблицю ідентифікаторів необхідно додати інформацію про номери рядків програми. У діалоговому вікні параметрів налагоджувача Debugging\Browsing (рис. 2.36), яке активізують із текстового меню Options\Debugger, можна повідомити компілятору, яку налагоджувальну інформацію потрібно генерувати: для використання вбудованого чи автономного налагоджувача (типу Turbo Debugger), чи для обох. За умови використання вбудованого налагоджувача обираємо параметр Integrated debugging/browsing (установлюється за замовчуванням). Вбудований налагоджувач Автономний налагоджувач Рис. 2.36. Вигляд діалогового вікна Debugging/Browsing Якщо розробляють велику багатомодульну програму, то налагоджувальна інформація часто виходить занадто об’ємною. Обсяг цієї інформації для окремих модулів можна скоротити, використовуючи в них директиву компілятора {$L-} чи скасовуючи в діалоговому вікні Compiler Options параметр Local Symbols {інформація про локальні ідентифікатори). При вилученні для якогось модуля режиму генерування інформації про локальні ідентифікатори, з налагоджувальної інформації для цього модуля вилучають всі ідентифікатори, описані у секції реалізації модуля. Для всіх ідентифікаторів інтерфейсної секції інформація генерується завжди, тому засоби налагодження функціонуватимуть.
2. МОВА BORLAND PASCAL 193 2.14.2. Виконання програми по кроках Команди покрокового виконання програми розташовані у пункті текстового меню Run (рис. 2.37). StepeSer^ ^ Щ- Виконання по кроках Трасе into F7 Покрокове трасування підпрограм llllllll'llllilli Виконання до курсора Pai»a»ete**s... Г Рис. 2.37. Вигляд меню виконання Run Trace into F7 - здійснює покрокове виконання головної програми та усіх підпрограм, які активізуються. За один виклик команди виконується оператор поточного рядка або один оператор, розташований у декількох рядках. Після чого виконання програми призупиняється. Потім знову можна виконати команду Trace into і т. д. Підпрограми, активізовані в процесі налагодження, також виконуються порядково. Бібліотечні (стандартні) функції в покроковому режимі не виконуються. Step over F8. Працює аналогічно попередній команді, проте підпрограми виконуються без трасування. Отож, покроково можна виконувати тільки оператори тексту поточної програми чи підпрограми, завантаженої у цей момент у вікні редактора. До початку покрокового виконання можна без трасування виконати фрагмент програми до контрольної точки або до курсора. Go to cursor F4 - виконує програму без трасування від початку чи від проміжної точки зупинки і до того рядка, у якому розташований курсор. Проте за необхідності, щоб програма зупинялася на заданому операторі завжди, коли вона його досягає, на ньому установлюють точку переривання. Program reset Ctrl + F2 - скидання програми, тобто повернення її у вихідний стан, завершує сеанс налагодження. Закриваються усі файли, відкриті в ній до цього 7 7-451
194 2.14. Налагодження програм засобами середовища ВР моменту. Після цього можна виправити текст програми і знову запустити її на виконання. Візьмемо, наприклад, таку програму: Program StepTest; Var і: Integer; Function Neg (X : Integer) : Integer ; Begin Neg := -X End; BEGIN For і := 1 to 10 do Writeln ( Neg (i) ) END. Якщо завантажити її у вікно редактора, то, натискаючи клавішу [fsL можна розпочати її покрокове виконання. У цьому випадку рядок виконання встановиться на оператор BEGIN, оскільки це перше, що виконується у програмі. Друге натискання клавіші F8 виконує BEGIN і переміщає рядок виконання вниз до оператора For. Наступне натискання [р#| активізує автоматичне виконання всього циклу For. На екран користувача виводяться числа від 1 до 10, а рядок виконання переміщається до End. Хоча функція Neg викликається 10 разів, рядок виконання ніколи на неї не переміщається, оскільки, у цьому випадку, весь цикл For виконається одразу. Отож, переглянути зміни під час виконання циклу неможливо. Проста зміна програми, однак, даватиме змогу це зробити: BEGIN For і := 1 to 10 do Writeln ( Neg (і) ) ; END. Оскільки оператор мови може займати декілька рядків, така програма буде цілковито еквівалентною попередній версії, а код, що генерується відповідно до неї, буде ідентичним. Внаслідок того, що оператор ІУгііеІп розташовано в окремому рядку, налагоджувач може інтерпретувати його окремо. У цьому випадку при багаторазовому натисканні клавіші рядок виконання в циклі 10 разів повертатиметься на УУгііеІп.
2. МОВА BORLAND PASCAL 195 2.14.3. Налагодження із зупинками Цей потужний варіант налагодження забезпечується командами підменю Debug - налагодження (рис. 2.38). ~T5öTs OptToni Windo Call stac Register Watch Output User screen Alt+F5 Eval uate/rodifу... Ctrl +F4 Add watch... Ctrl+F7 Add breakpoint... Визначення точки переривання Виклик стека підпрограм Відкрити вікно регістрів Відкрити вікно Watches Відкрити вікно Output Відкрити екран користувача Обчислити/модифікувати вираз Додати вираз у вікно Watches Встановити умови переривання Рис. 2.38. Команди підменю Debug Підменю Debug забезпечує доступ до таких засобів: • перегляд і зміна контрольованих значень змінних і виразів; • перегляд значень фактичних параметрів підпрограм, які активізувались; • роботу з точками переривання. Щоб ці засоби системи налагодження були доступними, установлюємо параметр Debug information у пункті текстового меню Options\Compiler. Точки переривання (контрольні точки) - це відповідні оператори програми, за умови досягнення яких відбувається призупинення процесу виконання програми. Після цього можна переглянути значення контрольованих виразів і змінних у вікні перегляду або їх виправити. Кількість точок переривання в програмі не обмежена. Контрольні точки можна задавати, вилучати, а також можна задавати умови зупинки в точці переривання. Задати чи зняти точку переривання можна за допомогою команди |о/+М Якщо для певного рядка встановлено контрольну точку, рядок виокремлюється червоним кольором. За командою Debug\Breakpoints відкривається діалогове вікно зі списком точок переривань. У ньому подано всі точки переривань у форщ таблиці, де зазначені:
196 2.14. Налагодження програм засобами середовища ВР • список точок переривань (Breakpoint List); • номер рядка (Line #), у якому встановлено точку переривання; • умову переривання - Condition (не обов’язково); • частотність проходження програми через певну точку - Pass, після якої необхідно зробити переривання програми. Команда Add breakpoint активізує однойменне вікно (рис. 2.40), у якому можна задати умови переривання і додати точку переривання на рядку, в якому розташований курсор. Після чергового запуску програми із заданими контрольними точками (наприклад, командою Ctrl+F$), компілятор призупинить виконання програми перед виконанням того оператора, що міститься у першій щодо виконання програми контрольній точці. Тоді можна переглядати і редагувати змінні програми. Цей спосіб є дещо гнучкішим, ніж використання методу виконання до позиції курсора (Go to cursor |fVb, оскільки в програмі можна задати декілька точок зупинки. Якщо це зробити всередині тіла циклу, то ми можемо контролювати стан змінних після виконання кожного витка циклу. ТооЗи Options Window ІЯГТtaels Hegiste* Hatch Output User screen Evaluate/« Add watch Add break) Рис. 2.39. Вигляд меню Debug рис 2.40. Вигляд вікна Add Breakpoint Команда Call stack відкриває та активізує вікно активних підпрограм. Під час кожного звертання до процедури чи функції усі фактичні параметри розташовані у програмному стекові. За допомогою цієї команди можна побачити оператори активізації підпрограм і значення їхніх фактичних параметрів. Оператори активізації представлені у послідовності, зворотній їхнім викликам, тобто верхньою у списку викликів стека буде підпрограма, активізована останньою, а нижнього - активізована першою. З метою аналізу роботи програми вбудований налагоджувач дає змогу переглядати поточні значення змінних, виразів і структур
2. МОВА BORLAND PASCAL 197 даних. Команда Watch відкриває й активізує вікно Watches - перегляду поточних значень змінних програми (рис. 2.41), де можна додавати чи вилучати елементи, які відстежуються, а також перевіряти значення змінних чи виразів, змінювати значення будь- яких змінних, у тім числі рядки, вказівники, елементи масиву і поля записів, що дає змогу перевіряти реакцію програми на різні умови. Рис. 2.41. Вигляд вікна Watches Команда Output відкриває й активізує вікно результатів, виведених на екран. Команда User screen відкриває екран користувача з результатами, виведеними на екран. Команда Evaluate\Modify (обчислити\модифікувати) обчислює значення виразу (чи змінної) у процесі налагодження, відображає результат обчислення і дає змогу, за необхідності, модифікувати значення змінних. Під час виконання програми у налагоджувальному режимі в будь-якій точці переривань за допомогою команди Evaluate можна обчислити і переглянути значення виразів, до яких належать змінні, визначені до цієї точки програми, і, за необхідності, змінити значення змінних програми. Команду Evaluate\Modify можна активізувати за допомогою клавіш Ctrl+F^ з вікна редактора під час призупинки виконання програми, наприклад, командою (ІР^| або [F^. 2.14.4. Відстеження і модифікація За покрокового виконання програми можна спостерігати результати її роботи декількома способами. Перший полягає у перемиканні, за необхідності, функціональною клавішею (ДО| вікон Edit та Output. У другому способі для виведення поточних результатів роботи програми можна відкрити додаткове вікно виведення, яке розташується нижче базового вікна Edit. Цього досягають або командою Add watch меню Debug, або комбінацією клавіш Q/+M У це вікно вводимо ідентифікатор змінної або вираз, зміну значення яких необхідно відстежити.
198 2.14. Налагодження програм засобами середовища ВР Рис. 2.42. Вигляд вікна Add Watch Обчислення і модифікація. Окрім перегляду виразів у процесі виконання програми, налагоджувач дає змогу у будь-який момент обчислювати вирази і змінювати значення змінних на етапі її покрокового виконання. Щоб обчислити вираз, обираємо команду Debug\Evaluate\Modify чи натискаємо комбінацію клавіш Ctrl+F^- Налагоджувач виводить діалогове вікно Evaluate and Modify (Обчислення і модифікація), що проілюстровано на рис. 2.43. За замовчуванням слово, на якому перебуває курсор у поточному вікні редагування, виводиться підсвіченим у поле Expression {Вираз). Цей вираз можна відредагувати, замінити іншим виразом чи обрати вираз, який обчислювали раніше, зі списку протоколу (його можна відкрити з допомогою кнопки (7J, розташованої праворуч поля Expression). Вираз будується відповідно до синтаксису мови. Він не повинен містити викликів функцій. Виведення результатів обчислення виразів відбувається' завдяки стандартним специфікаторам формату. Обидва способи обчислення і перегляду працюють на рівні виразів. Отож, визначимо, що вважатимемо виразом. Вираз складається з констант, змінних і структур даних, скомбінованих за допомогою операцій і вбудованих функцій. Майже усе, що Ви можете використовувати в правій частині оператора присвоювання, можна також використовувати при налагодженні. Поле для введення чи редагування виразу Поле для перегляду результату Поле для введення нового значення Рис. 2.43. Діалогове вікно Evaluate and Modify
2. МОВА BORLAND PASCAL 199 Після натискання Enter чи наведення курсора на кнопку Evaluate і натискання лівої клавіші миші, поточне значення результату обчислення виразу з поля Expression буде виведено у поле Result, або з’явиться повідомлення щодо помилки. Наприклад: • Error in expression - синтаксична помилка у виразі; • Unknown identifier - невідомий ідентифікатор; • Expression incorrectly terminated - обчислення припинено, оскільки обчислення виразу завершене некоректно. Модифікація змінних. Під час налагодження за допомогою діалогового вікна Evaluate and Modify поточне значення змінної можна змінити. З цією метою у полі Expression вводимо змінну, потім у полі New Value вводимо нове значення. Під час заміни значень змінних необхідно пам’ятати: • Змінювати можна тільки окремі змінні чи елементи масивів або записів, однак не самі масиви і записи. • Вирази в полі New Value повинні бути коректними з погляду синтаксису мови Pascal. • Внаслідок обчислення вираз у полі New Value повинен давати результат, сумісний за присвоюванням зі змінною, якій хочемо його присвоїти. Тут діє правило: якщо присвоювання спричинює при компілюванні помилку, то воно не є припустимим як значення модифікації. Щоб вийти з пункту Evaluate, необхідно натиснути клавішу lEscj кнопку Cancel чи закрити це вікно. Знайти у програмі опис процедури чи функції або визначення об’єкта, який нас цікавить у певний момент, можна за допомогою засобу перегляду об’єктів Object Browser. За допомогою пункту текстового меню редактора Search і вибору команд Objects, Units, Globals чи Symbols можна обрати необхідне вікно перегляду (рис. 2.44). Find.,. Replace... Search again Go to line number... Find error... Find procedure4,* —„ Рис. 2.44. Вигляд спадаючого меню команди Search
200 2.14. Налагодження програм засобами середовища ВР 2.14.5. Трасування складних програм Якщо у програмі використовуються об’єкти, то налагоджувач інтерпретує їхні методи аналогічно тому, як він інтерпретує звичайні процедури і функції. Покрокове виконання методу інтерпретує метод як один крок, повертаючи керування налагоджувану після того, як метод завершує виконання. Трасування методу завантажує і виводить на екран код методу і трасує його оператори. Якщо програма компонується із зовнішнім кодом, шляхом використання директиви компілятора {$ь <ім/я_файла>}, то якщо файл * 0Й/, який компонується, містить налагоджувальну інформацію, його код можна трасувати чи виконувати по кроках. ВР нічого не знає про код, який ми налагоджуємо в цих модулях, однак він показуватиме відповідні рядки у вихідному коді. Іноді не бажано виконувати по кроках усю програму тільки для того, щоб дійти до того місця, де виникла проблема. Налагоджувач дає змогу виконувати відразу великий фрагмент програми до тієї точки, з якої необхідно почати виконання по кроках. Щоб задати в програмі точку, до якої необхідно її виконати без зупинки, використовують команду Run\Go То Cursor чи натискають клавішу [ру|. З цією метою попередньо наводимо курсор на той рядок, з якого розпочинатимемо покрокове виконання, та активізуємо \F^. Це можна зробити як на початку сеансу налагодження, так і в процесі трасування частини програми. Пошук потрібного місця. IDE передбачає два способи пошуку заданого місця у програмі. Найпростіший спосіб надає команда Find Procedure {пошук процедури), що у меню Search. Ця команда запитує ім’я процедури чи функції, потім знаходить відповідний рядок у файлі, де описано цю підпрограму. Такий підхід доцільно використовувати під час редагування, однак його можна комбінувати з можливістю виконання програми до визначеної точки, щоб пройти програму до того її фрагмента, який необхідно налагодити. Повернення. Іноді під час налагодження корисно довідатися, як ми потрапили в цю частину коду. Вікно Call Stack {стек виклику), яке відкривається з пункту текстового меню Debug, подає послідовність викликів процедур чи функцій (глибиною до 128 рівнів), які спричинили до поточного стану. Це вікно доцільно використовувати, якщо випадково ми розпочали трасування фраг¬
2. МОВА BORLAND PASCAL 201 мента, який хотілося б виконати за один крок. У стеку викликів можна знайти той виклик, трасування якого вважаємо помилковим, потім обрати команду Run to Cursor, щоб виконати за один крок іншу частину фрагмента. Повторне виконання. Сеанс налагодження іноді доводиться розпочинати спочатку. Обираємо команду Run\Reset Program або натискаємо клавіші \Ctrl+F2j що передбачає цілковите скидання сеансу налагодження і дає змогу здійснити виконання по кроках чи трасування від початку головної програми. Відстеження виведення програми. Під час виконання програми по кроках інколи доцільно переглянути екран користувача. У прикладній програмі Windows це досить просто, оскільки програма уже виконується в окремому вікні. ВР передбачає кілька способів перегляду екрана користувача. Перемикання екранів. У будь-який момент сеансу налагодження можна виконувати перемикання екрана IDE та екрана користувача. Показ екрана користувача здійснює комбінація клавіш 4ft+F5|. Для повернення в IDE натисніть будь-яку клавішу на клавіатурі чи миші. При виконанні програми налагоджувач може також перемикати екрани автоматично. Керувати перемиканням екранів можна за допомогою параметрів Display Swapping (.Перемикання екрана) діалогового вікна Debugger. За замовчуванням задано ефективне перемикання, тобто екран користувача виводиться тільки в тому випадку, якщо виконуваний оператор виводить інформацію на екран чи активізує процедуру (навіть якщо ця процедура нічого на екран не виводить). Після завершення виведення екран перемикається назад у IDE. Ми також можемо повідомити налагоджувачу, що перемикати екрани необхідно на кожному рядку, незалежно від виведення, чи не перемикати їх зовсім. Перемикання екранів для кожного рядка доцільно використовувати, якщо наша програма виводить інформацію безпосередньо на екран, що може затерти вміст екрана IDE. Вікно Output з результатами роботи програми можна подивитись, якщо активізувати команду меню Debug\Output. Додавання виразу для перегляду. Щоб додати у вікно Watches змінну, оберіть команду Debug] Watch\Add Watch чи натисніть клавіші |Cfr/+F7|. Якщо вікно Watches є активним, можна додати
202 2.14. Налагодження програм засобами середовища ВР вираз перегляду, натискаючи клавішу |/>fs|. Налагоджувач відкриє діалогове вікно із запитом про тип виразу, що переглядають. За замовчуванням виразом слугує слово в позиції курсора поточного вікна редагування. Вирази, які переглядають і які опрацьовано раніше, зберігаються у списку протоколу. Відстеження поточного виразу, який переглядають. Останній доданий чи модифікований вираз, який переглядають, є поточним виразом, який переглядають, про що засвідчує виведений ліворуч від нього символ жирної точки. Якщо вікно Watches активне, можна також вилучити поточний вираз, натискаючи клавішу [Рг/1 чи ІО/+И Щоб видалити усі вирази, що переглядаються, оберіть команду Debug\Watch\RemoveAll Watches. Редагування виразів, які переглядають. Щоб відредагувати вираз, який переглядають, необхідно навести на нього курсор і двічі натиснути ліву клавішу миші, або зробити цей вираз поточним, потім натиснути клавішу \Enterн чи обрати команду Debug\Watch\Edit Watch. Налагоджувач відкриє діалогове вікно, аналогічне вікну для додавання виразу, який переглядають, що дає змогу відредагувати поточний вираз. При виборі командної кнопки ОК чи натисканні клавіші Enter*- відредагований вираз замінює оригінал. Форматування виразів, які переглядають. Вікно Watches дає змогу декількома способами форматувати вирази, які переглядають, додаючи' один чи більше специфікаторів формату. Наприклад, хоча цілочисельні значення вводять, зазвичай, у десятковій формі, можна задати виведення виразу і в шістнадцятковому форматі, указавши після нього Н. Використання точок зупинки. ВР дає змогу з метою налагодження встановлювати у своїй програмі точки зупинки. Точка зупинки - це позначена в тексті програми позиція, у якій передбачено припинення виконання програми і повернення управління налагоджувачу. У цьому сенсі точка зупинки працює аналогічно команді Go to Cursor, за якої програма виконується звичайним шляхом до досягнення визначеної точки. Головна розбіжність полягає в тому, що можна задати декілька точок зупинки, які спрацьовуватимуть щоразу за їхнього досягнення. Задавання точок зупинки. Щоб установити у своєму коді точку зупинки, переміщаємо курсор на той рядок, де потрібно
2. МОВА BORLAND PASCAL 203 зупинитися. Рядок повинен містити виконуваний код і не може бути коментарем, описом чи порожнім рядком. Вибір команди Toggle Breakpoint у локальному меню вікна редагування чи натискання клавіш |Or+F3| установлює на рядку точку зупинки* що позначається підсвічуванням усього рядка червоним кольором. Отож, під час виконання програми з IDE вона зупинятиметься за досягнення цього рядка, а саме перед його виконанням. Рядок, що містить точку зупинки, виводиться у цьому випадку у вікні редагування як рядок виконання. У цей момент можна виконати будь-які інші дії з налагодження (виконання програми по кроках, трасування, перегляд, обчислення значень). Скасування точки зупинки. Поміщаємо курсор на рядок, що її містить, й обираємо у локальному меню вікна редагування команду Toggle Breakpoint або натискаємо комбінацію клавіш Ctrl+FS\. Модифікація точок зупинки. Під час сеансу налагодження IDE відстежує всі точки зупинки. Замість того, щоб відшукувати у вихідному коді точки зупинки, воно дає змогу обслуговувати точки зупинки в одному діалоговому вікні Breakpoints. З метою виведення цього діалогового вікна необхідно обрати команду Debug\Breakpoints. У цьому діалоговому вікні можна встановлювати, вилучати, редагувати і переглядати усі точки зупинки. Рис. 2.45. Діалогове вікно Breakpoints Призначення командних кнопок діалогового вікна Breakpoints: • Edit використовують для додавання нових точок зупинки або модифікування виокремлених нами існуючих точок. С • Delete скасовує виокремлену нами точку зупинки. • View допомагає знайти у тексті програми точку зупинки.
204 2.14. Налагодження програм засобами середовища ВР • Clear All вилучає усі точки зупинки. Створення умовних точок зупинки. Точки зупинки, додані командою Toggle Breakpoint, є безумовними: якщо потрапити на цей рядок, налагоджувач у будь-якому випадку зупинить програму. Редагування нової чи існуючої точки зупинки передбачає дві додаткові можливості - за допомогою параметрів діалогового вікна Edit Breakpoint можна створити умовні точки зупинки. У цих точках зупинки можна задати два види умов: лічильник виконань і логічні умови. Обчислення кількості проходжень (встановлення для точки зупинки лічильника проходжень). Повідомляє налагоджувачу, що зупиняти програму необхідно не при кожному досягненні точки зупинки, а тільки на N-й раз: якщо лічильник проходжень дорівнює З, то налагоджувач зупиняє програму тільки за умови досягнення ціа точки зупинки втретє. Перевірка умов. Умовою для точки зупинки може також слугувати вираз типу Boolean. Наприклад, можна перевірити, чи потрапляє змінна у заданий діапазон, або чи встановлено деякий прапорець. У таких умовах для точок зупинки можна задавати будь-які булівські вирази, що задовольняють правилам мови ВР. Переривання програми без точок зупинки. Навіть якщо точки зупинок і не встановлено, все таки при виконанні програми з IDE у будь-який момент можна зайти у налагоджувач, натискаючи Сігі+Вгеаїц. Налагоджувач відшукує позицію у вихідному коді - там, де перервано програму. Як і у випадку звичайної точки зупинки, можна потім виконати програму по кроках, трасувати її, від стежити чи обчислити вираз.
3. РОЗВ'ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ Розділ присвячено вивченню головних методів та алгоритмів комп’ютерного розв’язування двох типів систем рівнянь: • систем лінійних алгебричних рівнянь (СЛАР); • систем нелінійних алгебричних і трансцендентних рівнянь (СНР). Досліджено також проблеми, які виникають під час розв’язання таких рівнянь. До розв’язання перелічених систем зводиться значна кількість фізичних та інженерних задач. Незважаючи на те, що класичні алгоритми реалізації цих методів детально розроблено й описано, їх застосування в обчислювальній практиці ускладнюється тим, що вони надто чутливі до таких понять, як точність обчислень, обумовленість матриць коефіцієнтів та ін. Отож, вивчення математичних та алгоритмічних ідей цього розділу є вкрай важливим для успішного розв’язання названих задач. 3.1. Системи лінійних рівнянь Проблема чисельного розв’язування систем лінійних алгебричних рівнянь цікавить математиків уже чимало сторіч. Перші математичні результати датовані ХУІЦ століттям. У 1750 році Г. Крамер (1704-1752) опублікував свої праці про визначники квадратних матриць і запропонував алгоритм обчислення оберненої матриці (правило Крамера). У 1809 році К. Гаус (^1777—1855) опублікував роботу, присвячену руху небесних тіл, в якій подано метод розв’язування лінійних систем, відомий як метод виключення.
206 3.1. Системи лінійних рівнянь У другій половині XX століття з виникненням комп’ютерів зросло зацікавлення до чисельних методів. Розпочалось активне дослідження вже існуючих методів з метою їхньої реалізації на ЕОМ. Робилися спроби підвищити їхню точність. Унаслідок обмеженості ресурсів ЕОМ чималого значення надавали підвищенню швидкодії алгоритмів. Сьогодні, у зв’язку з наявністю потужних комп’ютерів, обмеження щодо оперативної пам’яті та швидкодії ЕОМ дещо втратили актуальність. Найчастіше, коли йдеться про розв’язування СЛАР, мають на увазі таку задачу: дано систему з N рівнянь, що містить N невідомих. Ця система має один і лише один розв’язок, який необхідно знайти. Що стосується методу розв’язування, то найчастіше обирають метод Гауса. Насправді існує чимало різноманітних методів розв’язування таких задач, а також їхніх постановок. Отож, доцільно класифікувати задачі, що стосуються СЛАР, методи їхнього розв’язування і проблеми, які виникають у цьому випадку. Виокремимо найважливіші типи задач: • “Класична” постановка - кількість рівнянь дорівнює кількості невідомих, визначник матриці системи не дорівнює нулю (система має лише один розв’язок). • Узагальнений варіант - кількість невідомих більша від кількості рівнянь* система рядків матриці коефіцієнтів є лінійно-незалежною (така система завжди має розв’язок, іноді не один). • Задача без обмежень на розмір матриці системи та її властивості. Можлива відсутність точного розв’язку (у такому випадку можна шукати якнайліпше наближення до нього). • Задача з матрицею, що має один зі спеціальних видів (скажімо, тридіагональною або симетричною). Такі системи розв’язують спеціальними методами ефективніше, ніж загальними. • Матриця системи розріджена, тобто число ненульових її елементів порівняно мале. Тут найефективнішими є ітераційні методи. • Замість однієї системи існує набір систем рівнянь із загальною матрицею коефіцієнтів і різними правими частинами. Спеціальні методи вирішують такі задачі за
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 207 один прийом, причому швидше, ніж загальні методи, що розв’язують системи по одній поступово. Перша група методів розв’язування систем лінійних рівнянь налічує прямі методи обчислення розв’язків системи рівнянь з невиродженою квадратною матрицею коефіцієнтів. їх ще називають методами з відомим числом арифметичних операцій: • Метод Крамера, зазвичай, використовують тільки в теоретичних дослідженнях для доказу принципової можливості розв’язання досліджуваної задачі. На практиці його не використовують через низьку швидкодію роботи (трудомісткість його порядку И\ операцій). • Метод Гауса (звичайний або модифікований) - простий метод, який найчастіше використовують на практиці. • Методи віддзеркалень та обертань - методи, в яких для занулення елементів матриці використовуються лінійні перетворення особливого вигляду, що дає змогу зменшити накопичення похибок у випадку погано обумовленої системи. За швидкодією вони у понад 1.5 рази повільніші, ніж метод Гауса. • Різновидом слугує модифікація методу обертань, яка дає змогу розв’язувати набори систем лінійних рівнянь з однаковими лівими частинами. Зрозуміло, розв’язок такої задачі можна одержати, розв’язуючи системи з набору почергово. Проте існують ефективніші методи, що дають змогу прискорити процес розв’язування шляхом врахування у поставлених задачах рівності лівих частин. Складнішим є випадок, коли матриця коефіцієнтів вироджена, або навіть прямокутна. У такому випадку перелічені методи вже непридатні, оскільки розв’язок може взагалі не існувати або бути не єдиним. Тут застосовують такі методи: • Метод ортогоналізації. Цей метод вирішує задачу з матрицею розміру (М хТУ), а за відсутності точного розв’язку шукає якнайліпше наближення до нього. Зазначимо недоліки методу: він працює у 3-4 рази повільніше, ніж метод Гауса; для погано обумовленої матриці похибки під час роботи накопичуються надто ґ швидко. Проте, якщо система добре обумовлена, а метод Гауса є щодо неї непридатним, ортогоналізація -
208 3.1. Системи лінійних рівнянь непоганий вибір. Існує також узагальнення цього методу на випадок довільної норми вектора нев’язки. • Метод сингулярного розкладання. Метод також вирішує задачу із будь-якою матрицею (М х И), а за відсутності точного розв’язку шукає якнайкраще наближення до нього. Щодо цього обчислюється фундаментальна система розв’язків, необхідна під час пошуку власних векторів. Цей метод вважають найпотужнішим із відомих. Він дуже стійкий, що вигідно відрізняє його від методу ортогоналізації, добре справляється з виродженими матрицями. Єдиний недолік - цей метод у 10-12 разів повільніший, ніж метод Гауса. Вивчення ідей розв’язання СЛАР розпочнемо із розгляду простих випадків. 3.1.1. Рівняння з одним невідомим Рівняння вигляду а-х = Ь , де а і Ь - вирази, залежні тільки від параметрів, ах- невідоме, називають лінійним щодо х. Це рівняння при аф 0 має єдиний розв’язок х = — за допустимої а множини значень параметрів. При а = 0 і Ь = 0 будь-яке значення х слугуватиме розв’язком. При а = 0 і Ь Ф 0 розв’язку немає. * 3.1.2. Системи двох лінійних рівнянь з двома невідомими Лінійною , системою двох рівнянь з двома невідомими називають систему: ІЧ,і*+°і,2 у=ь\ \а2,іХ + а2 2у=Ь2 ' Цю систему можна розв’язати графічно. З цією метою перепишемо систему так:
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 209 = ЬгаиїХ Яі. 2 __ Ьг~~&г, іX ^ СІ2,г Побудуємо графіки кожної із функцій у(х), які формують нашу систему. Залежно від значення коефіцієнтів ми отримаємо один із чотирьох випадків, які наведено на рис. 3.1: Рис. 3.1. Варіанти графічного розв’язування системи двох лінійних рівнянь з двома невідомими Перший випадок - система розв’язків не має, графіки паралельні один до одного. У другому варіанті система має безліч розв’язків, графіки накладаються. У четвертому випадку можна чітко визначити пару чисел (хІ9ух), які є розв’язком нашої системи. Третій випадок є найнеприємнішим. Кути нахилу кожного із графіків до осі Ох мало відрізняються, що утруднює визначення точки їхнього перетину. Остання розташована десь поміж двома вертикальними лініями, які ми нанесли на графік. Кажуть, що матриця коефіцієнтів системи у цьому випадку є погано обумовлена. 3.1.3. Формулювання узагальненої задачі До розв’язування СЛАР зводять значну кількість задач обчислювальної математики. Нагадаємо: розв’язком СЛАР є вектор х = (х[ , х2 ,..., хк )т , що задовольняє рівняння: Ах=Ь , (3.1.1) де А - ьртриця розмірності (ТУхТУ) і Ь =(1\ ,Ь2 ,...,6^ У - заданий вектор правої частини системи. Для простоти і наочності
210 3.1. Системи лінійних рівнянь викладу вважаємо, що А , Ь і X містять елементи дійсного типу. Припускаємо також, що беХА Ф 0. Це гарантує наявність розв’язку задачі (3.1.1) і його єдиність. Існують дві великі групи методів розв’язання задачі (3.1.1): прямі та ітераційні. Перші дають розв’язок за скінченну кількість кроків. їх ще інколи називають “точними” (проте “точними” ці методи можна вважати, нехтуючи похибками заокруглення). До цієї групи зачислено, наприклад, відомі методи Крамера і Гауса. Ітераційні методи генерують послідовність хі , яка при і -> оо (/ - номер ітерації) може збігатися до розв’язку Ґ. Критерієм закінчення ітераційного процесу, зазвичай, слугує виконання нерівності: ||^и _ ^м;|| < є (3л 2) Як прямі, так і ітераційні методи мають свої області переважного застосування. 3.1.4. Зведення матриці системи до трикутного вигляду Практично всі чисельні методи, що належать до класу прямих, використовують розкладення матриці системи на співмножники, один з яких неодмінно повинен бути трикутною матрицею. Можливість розкладення квадратної матриці на трикутні співмножники доводить наступна теорема, яку ми наведемо без доведення. Теорема 1. Яка б не була квадратна матриця А порядку N з відмінним * від нуля головним мінором до {И-іуто порядку включно, її завжди можна представити як добуток матриць Ь і £/, що є, відповідно, нижньою і верхньою трикутними матрицями [85]. Зазначимо, що розкладання квадратної неособливої матриці на трикутні співмножники не є єдиним. Справді: ЇМ = ЬО~хВи = (ЬО~1)- (£>[/). Якщо В- діагональна матриця, то матриці і ПП залишаються трикутними, проте Ш~Х Ф Ь і ПІ] Ф V. Якщо ж зафіксувати значення Іі і або иі і (наприклад, покласти /; , =1), то
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 211 розкладення буде єдиним. Саме таке розкладення (при /,, = 1) називають 1 [/-розкладом квадратної матриці. Поняття визначника досить рідко використовують у практиці програмування фізичних задач, проте його широко використовують математики. Сама по собі величина визначника деякої матриці не має відношення до достовірності обчислень, хоча фразу “оскільки визначник системи рівнянь дорівнює нулю, система не має розв’язків” можна почути часто. Отож, наш алгоритм обчислення визначника має швидше академічне, аніж практичне значення. Нехай А є квадратна матриця порядку N, де N > 1. Визначником квадратної матриці А порядку N називають число: матриці порядку (N -7), одержаної з матриці А шляхом вилучення 1 -го рядка та / -го стовпця. лення визначника шляхом розкладення за першим рядком. Число Нехай М^}> - визначник квадратної матриці порядку {И -1), одержаної з матриці А вилученням і -го рядка та у -го стовпця (мінор елемента ^ •). Число (-1);+1м,<7> називають алгебричним доповненням елемента аі . матриці А. Справедливі формули обчислення визначника квадратної матриці А розкладенням по і -му рядку та розкладенням по у -му стовпцю: 3.1.5. Обчислення визначника матриці 7=1 Дл^і аN,2 * ■ * Ям,АГ де М\]> - мінор елемента аХ]-, тобто визначник квадратної Формулу Асі А = і; аи(-іУ+1Мі^ називають формулою обчис- називають алгебричним доповненням елемента о, ..
212 3.1. Системи лінійних рівнянь сіеіА = ді,і а і,2 я 2,1 02,2 ам,\ а N,2 Д1.ЛГ 02^ акм = Е аі,к{-\ТкМЇк> = Е (3-1 -4) і=1 • ’ N ;Е *=1 для/ = 1,2,...,ЛГ, ;' = 1,2,...,М Для квадратної матриці другого порядку формула обчислення визначника є такою: сієї ■4,1 ^*2,1 1,2 “2,2 '1,1 “1.2 *2,1 *2,2 “*1,1 '*2,2 “*1,2 ’*2,1> оскільки, наприклад, у формулі розкладення визначника по 1-му рядку М\Х> = а22, МГ2> = а2,. Для квадратної матриці третього порядку формула обчислення визначника розкладенням по 1-му рядку набуває вигляду: / \ *1.1 а\ 7 а\ 1 яц і О'у сієї *1,1 *1,2 *1,3 *2,2 *2,3 *2,1 *2,3 *2,1 *2,2 *2,3 = «1.1 *3,3 *1,2 *3,3 + *1,3 *3,2 *3,1 *3,1 *3,2 «3.3; '2,1 м2,2 *3,1 *3,2 Одним із оптимальних способів обчислення визначника квадратної матриці А розміру (N х N) є спосіб, що використовує зведення матриці до трикутного вигляду з вибором максимального елемента. Алгоритм обчислення визначника: • У першому стовпці визначаємо максимальний елемент Мх. Якщо він знаходиться в у -му рядку, то перший і У -й рядки міняємо місцями. При Мг = 0 визначник дорівнює нулю. • 3 елементів (у >1) віднімаємо відповідні елементи першого стовпця, помножені на ±І аи
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 213 Одержимо: сієї А — — сіу і 1 0 . 0 а2,1 «1,1 ат 2,2 а(,) 2,И — (3.1.5) аИ, 1 ам я(1) N,2 ■ а(1) •• аи,и де <$] =аи аі, 1 %а\^ а, До визначника матриці застосовуємо цей прийом ще (N -2) раз.Остаточно <|>держимо: А -а -я(1) • .д(АМ) ““1,1 2,2 ••• ‘ Під час переставляння стовпців враховуємо зміну знака визначника. Зазначимо, що в алгоритмі відбувається порівняння чисел з нулем. Оскільки всі операції на комп’ютері виконуються з деякою похибкою, то для порівняння в алгоритм передається мале число £/75, з яким і відбувається порівняння. Будь-яке число, за модулем менше £рт, вважатимемо нулем.
214 3.1. Системи лінійних рівнянь Функцію, яка обчислює визначник згідно з нашим алгоритмом, наведено нижче. Її доцільно зберегти на диску у файлі з іменем Det_XIO.pas. Function Det (A: Matrix; N: Integer; Eps: Real) : Real; Var і, j, k : Integer; t, Q, R : Real; Begin R := 1; For k := 1 to N do Begin Q:=0; For і := k to N do Begin t := A[i, k] ; If Abs(t) > Abs(Q) then Begin Q := t; j := і End End; If Abs(q) < Eps then Begin R := 0; k := N + 1 End else Begin If j ok then Begin R := -R; For і := k. to n do Begin ' T := A[j, i] ; A[j, i] := A[k, i]; A[k, i] := t End End;b For і := k + 1 to N do Begin t := A[i, k] / Q; For j := k + 1 to N do A[i, j] := A[i, j] - t * A[k, j] End; R := R * A[k, k] End End; Det := R End;
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 215 Дослідження правильності та ефективності нашої підпрограми можна здійснити, використовуючи головну програму: Program Xio_Gol_Pr; Uses Crt; Type Matrix = Array [ 1. . 5, 1..5] of Real; Vec = Array [1..5] of Real; Var A : Matr; X, В : Vec; i, k, j, L, N : Integer; R, D, Eps : Real; {$1 Det_XIO.pas} { Під'єднання файла функції Det } BEGIN ClrScr; Eps := 0.001; N := 4; а[1,1] := 2; а[1,2] = 0; а[1,3] = 1; а[1,4]:= 3 а[2,1] :=-1; а[2,2] = 2; а [2, 3] =-1; а[2,4]:= 1 а [3,1] := 0; а[3,2] = 1; а[3,3] = 0; а[3,4]:=-2 а[4,1] := 1; а[4,2] =-3; а[4,3] = 2; а[4, 4]:= 1 Ь[1] := 6; Ь[2] = 1; Ь[3] =-1; Ь[4]:= 1 D := Det(A, N, Eps); Writeln ('Визначник Det= ' , D); Repeat Until KeyPressed END. 3.1.6. Метод Крамера Одним із практичних застосувань алгоритму обчислення визначника j квадратної матриці є програмування відомого методу Крамера для розв’язування CJ1AP третього порядку (N = 3). Запишемо цю систему: '^+^,2У + аІ^ = Ь1 < а21х+а22у+а2>3z = b2. (3. і.6) a3,ix+ax2y+a3'3z = b3 Введемо позначення визначника системи: aU «1,2 аі,з А = а2,\ а2,2 а2,3 а3,1 ґ аЪ,2 а3,3
216 3.1. Системи лінійних рівнянь Якщо АїО, тоді розв’язок системи (3.1.6) однозначно обчислюється за формулами Крамера: д • д Ах: = Ау = Дг = <1< II * - у=- °и а.,з *2 °2,2 а2,3 *3 *3,2 аз,з ам а.,з °2,3 % *з °3,3 а.,1 °.,2 \ °2., °2,2 К % "з,2 А3 * (Д*0), де: Завдання для самостійної роботи Запрограмувати формули Крамера, використовуючи функцію БеЪ. Порівняти швидкодію розв’язування цим методом СЛАР різних порядків зі швидкодією алгоритму Гауса, який наведено нижче.
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 217 3.2. Метод Гауса розв’язування систем лінійних рівнянь Метод Гауса містить два етапи: • прямий хід - послідовне вилучення невідомих з рівнянь системи для перетворення початкової системи (3.1.1) в еквівалентну їй систему з трикутною матрицею; • зворотна підстановка - визначення компонент вектора х*, що є розв’язком системи. 3.2.1. Обчислювальна схема Запишемо систему (3.1.1) у скалярній формі: «1,1*1+«1,2*2 + «1,3*3+ •••+«1,ЛГ*ЛГ -1\ «2,1*1 +«2,2*2 +«2,3*3 + < -• + «2,ЛГ%=62 ! . (3.2.3) >,1*1 +«//,2*2 +«N,3*3 +••• ••• +аИ,ИхИ Частина коефіцієнтів аі} може дорівнювати нулю, проте перестановкою рівнянь завжди можна домогтися, щоб Яц* 0. Перше рівняння системи (3.2.3) після поділу його на елемент а1д набуває вигляду: + = А. «1,1 «1,1 «1,1 «1,1 Або х1 + /, 2х2 + /і, з*з + + Л мхк = 8і > (3 -2-4) де: /Х ] =Ях>;/Оід , gl = —. Рівняння (3.2.4) помножимо на а21 аи і віднімемо його з другого рівняння системи (3.2.3): а2,1Х1 + а2,2*2 + + + а2УХії ~ ^2 а2,\х1 + а2,\ А,2х! + ^.іЛз^ІЗ + + = ^,1^1 (Ог 2 - «2,і/і,2 ) х2 + (а2,3 “ а2,іУі,3 ) *3 + + (<*2,# “ <*2,1 ./І,# ) % “ ^2 “ ^,1^1
218 3.2. Метод Гауса розв’язування систем лінійних рівнянь Перепишемо останнє рівняння, перпозначивши його коефіцієнти: «Й *2 + а2,3 *3 + + ХМ = № • (3-2-5) Послідовно домножуючи рівняння (3.2.4) на а31....аМІ і віднімаючи одержані рівняння з 3-, 4-, ..., Лґ-го рівнянь системи (3.2.3), перетворимо всі її рівняння до вигляду, аналогічного (3.2.5). Після завершення цих перетворень (першого кроку прямого ходу алгоритму Гауса) одержимо систему: ^1,2Х2 '*• =^1 *2*2 + +а%ХМ=Ь2) °3,2^2 ^аз]^хи = ^*3 ^ (3.2.6) д(1)х + + а(1) г -А0) аМ,2Х2 + + аМіКхИ - Коефіцієнти другого і подальших рівнянь цієї системи обчислені відповідно до виразів: *8 =аі,га<Аі > Ь?)=Ьі-аи\ 8і (*,У)^2. (3.2.7) Після успішного виконання усіх (N-1) кроків вилучення одержимо систему вигляду: 1-Ху+ /12х2 + /1(3*3 + + /імхи = gl Ь*2+ +а%ХК=Ь2) 1-х + +а(Ь1)х -6(М) (3-2-8) 1 Хк + + акМ % “ °к _А(ЛМ) аИ,Ы ХИ -°1Я На цьому прямий хід алгоритму Гауса завершено, оскільки система (3.2.8) має трикутну матрицю. Розрахункові формули перетворення системи (3.2.3) в систему (3.2.8) є такі: для к = 1, 2, ..., N-1 виконати наступні перетворення системи рівнянь: аиІ =аи/1)- а?кЛ^к,/ , і = к + 1./V; ] =
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 219 fKj=-<3-2-9> “к,к h(k-1) h(k) _/,(*-!) _а«Л) „ _ °к ' °/ “ °і аі,к 6к > 8к ~ (іг.і) • ак,к Зворотною підстановкою називають етап розв’язання системи (3.2.8). З її останнього рівняння знаходимо: x*N = Ь^Л)/ Далі, з (N-J)-го рівняння легко обчислюється чергова компонента розв’язку: * _ (h(N-2) (N-2) * w_(tf-2) XN-1 “ \°N-\ aN-\,N XN)/ “NA.NA ■ Усі подальші компоненти вектора розв’язку обчислюють за формулою: *;=(^/+1)- І; 4[-рх])/а\^\ i = N-, (3.2.10) j = i +1 яка описує зворотний хід алгоритму Гауса. Важливою характеристикою чисельного методу є його трудомісткість. Для алгоритму Гауса можна одержати такі оцінки. За достатньо великих значень N для прямого ходу необхідно 2 N3 порядку - - операцій додавання і множення, а для зворотного N2 ходу - Бачимо, що трудомісткість алгоритму визначається, здебільшого, прямим ходом. 3.2.2. Алгоритм методу Гауса Алгоритм розв’язування CJIAP за методом Гауса, який ми розглянули вище, можна представити блок-схемою, яку подано на рис 3.2. У нашому алгоритмі блоки 4-33 виконують прямий хід методу Гауса (зведення матриці до трикутного вигляду). З них блоки 5-10 знаходять максимальний елемент /-го стовпця матриці А. Якщо ним не є діагональний елемент, блоки 14-18 здійснюють перестановку рівнянь системи так, щоб максимальний елемент потрапив на діагональ. Блоки 34-43 виконують зворотний хід
220 3.2. Метод Гауса розв’язування систем лінійних рівнянь методу Гауса згідно з виразом (3.2.10), що передбачає знаходження розв’язку х =(*і ,х*2 х*и )т нашої системи. Завдання: написати, згідно з алгоритмом (див. рис. 3.2), процедуру методу Гауса і зберегти її у файлі (га»го./мю . Рис. 3.2. Блок-схема алгоритма методу Гауса розв’язування СЛАР \А^<1Е-7
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 221 3.2.3. Головна програма для розв'язання СЛАР Нижче наведено головну програму, яка вводить розмір СЛАР N, матрицю А і вектор Ь, активізує нашу процедуру для обчислення розв’язку системи, після чого виводить розв’язок на екран. Program Xio_Gol__Pr ; Uses Crt; Type Matrix = Array [1..10, 1..10] of Real; Vec = Array [1..10] of Real; Var A : Matrix; x , b : Vec; і , k , j , L , N : Integer; R : Real; {$1 Gauss.pas) BEGIN ClrScr; Write(1 Введіть розмір матриці N='); Readln (N); Write ('Вводьте матрицю'); L := 5; For і :=1 to N do Begin k := 1; For j := 1 to N do Begin GotoXY (k , L) ; Write ('A[' , i, ',' , j, ']='); Read (A[i, j]); k := k + 16 End; L := L + 1 End; Writeln ('Введіть вектор правої частини'); k^^l; For і := 1 to N do Begin GotoXY (k, N + 6) ; Write (fb[', i, ']='); Read (b[i]); k := k + 16 End; Gauss (A, h, N, x) ; Write _(' Розв1 ' язок: ') ; For і := 1 to N do Begin GotoXY {1, N + 7 + i); Write ('x[', i, ']=', x[i]) End; Repeat Until KeyPressed END.
222 3.2. Метод Гауса розв’язування систем лінійних рівнянь 3.2.4. Процедура методу Гауса Procedure GAUSS (A: Matrix; В: Vec;N: Integer; Var X: Vec) ; Var і, j, k : Integer; R : Real; Begin If N = 1 then If Abs (A[l, 1]) < IE-7 then Begin Writeln (’Система є виродженою'); Repeat Until KeyPressed; Halt End else Begin X[ 1] := В[ 1] / A[l, 1]; Exit End; For і := 1 to N - 1 do Begin k := i; R := Abs (A[i, i] ) ; For j := і + 1 to N do If Abs (A[j, i]) >= R then Begin k := j; R := Abs (A[j, i]) End; If R <= IE-7 then Begin Write ('Система є виродженою'); Repeat Until KeyPressed; Halt End; {Якщо діагональний елемент не найбільший - переставляємо рядки} If k ь<> і then Begin R := B[k] ; В[k] := В[і]; В [і] := R; For j:=і to N do Begin R := A[k, j]; A[k, j] := A[i, j]/ A[i, j] := R End End; R := A[i, i]; B£i] := В[i] / R;
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 223 For j:=1 to N do А[і, j] := A[i, j] / R; For k := i+1 to N do Begin R := A[k, i]; В[k] := B[k] - R * B[i]; A[k, i] := 0; For j := і + 1 to N do A[k, j] := A[k, j] - R * A[i, j]; End; End; If Abs (A[N, N]) <= IE-7 then Begin Write (’Система є виродженою')/ Repeat Until KeyPressed; Halt End; { Зворотний хід } X [N] := В [N] / A[N, N] ; For і := N - 1 downto 1 do Begin R := В[i]; For j := і + 1 to N do R := R - A[i, j] * X[j]; X[i] := R End End; 3.2.5. Тестова задач Задача. У колі, що на рис. 3.3, знайти^с^руми Ji, Т2, Із для заданих значень номіналів. Розв’язок. Згідно із /7-м законом Кірхгофа, сума спадів напруг по будь-якому замкнутому контуру, при обході його у вказаному напрямі, дорівнює нулю. Застосовуючи цей закон до нашого кола (рис. 3.3), одержимо систему лінійних алгебричних рівнянь. Рис. 3.3. Електричне коло У загальному випадку система набуде такого вигляду:
224 3.2. Метод Гауса розв’язування систем лінійних рівнянь (Я,+Л3+/?<)/,+ Яз 12 ^4 ^ З — ^5) 12^~ ^5 І З Е>2 Я5І2+ (^4+^5+^б)^3 =^‘ ^зЛ + (Л2+Л3+Л5)/2 + Підставляючи у систему числові значення номіналів, одержимо: Розв’язуючи її, одержуємо шукані значення струмів: . Іг =0.34; /2 = 0.64; І3 = -0.38. Від’ємний знак струму І3 засвідчує, що напрям обходу третього контуру ми обрали протилежний до справжнього напряму протікання струму. У матричній термінології метод Гауса, розв’язуючи систему Ах = Ь , перетворює її в деяку еквівалентну систему С/х — у , де и - верхня трикутна матриця, а у - вектор перетвореної правої частини рівняння Ь . Очевидно, що можна побудувати деяку матрицю Ь, яка завдяки множенню на вектор у даватиме вектор к Ь , тобто Ьу =Ь . Звідси у = 17і Ь . Тоді С/х =І71 Ь . Ы7х =Ь . Матриця А замінена добутком двох матриць: . Цю замі¬ ну називають алгоритмом Ы) -перетворення. Необхідність у подібному алгоритмі є значною, оскільки існує чимало задач, для яких матриця А є незмінною, або малозмінною, а вектор Ь для кожної задачі є іншим. Очевидно, що нема сенсу, розв’язуючи серію таких задач, кожен раз наново перетворювати матрицю А до трикутного вигляду. Використати ж один раз одержану трикутну матрицю неможливо, оскільки в процесі її зведення перетворюється також 130/!+ 20 Д + 100/,+ 20/2+ 75 /2 + 40/2+ 100/3 =20 40/3 =40 160/3 =0. 3.3. Метод 1.17-перетворення
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 225 вихідний вектор b . Отож, необхідно послідовність перетворень вектора Ь якось запам’ятати і використовувати при формуванні перетвореної правої частини кожної наступної системи. Це здійснено завдяки матриці L. Правомірність такої операції задає теорема про LU - перетворення: Якщо всі кутові мінори матриці А відмінні від 0, то матрицю А можна однозначно представити як дві матриці A = LU (Upper і Lower) [85]. 3.3.1. Алгоритм іи-перетворення Алгоритм методу Гауса в інтерпретації Z {/-перетворення полягає у наступному. Формуємо дві окремі процедури Decomp і Solve. У процедурі Decomp: 1. Здійснюємо вибір максимального елемента у першому стовпці матриці А і, шляхом перестановки рядків системи (3.2.3), поміщаємо його на місце аІ}. З цією метою змінній change цілочисельнного типу, яка є вихідним формальним параметром процедури Decomp, спочатку надаємо значення 1. Якщо, за умови пошуку максимального елемента, його номер у стовпці матриці А виявиться відмінним від 1, заносимо цей номер у змінну Change. Це значення буде передане у процедуру Solve і використане там з метою обміну елементів вектора b . Вибір максимальних елементів у наступних стовпцях матриці А наш алгоритм не здійснює. Обидві трикутні матриці L і U формуємо водночас. Матрицю L формуємо послідовно за стовпцями, а матрицю U - за рядками. Це дає змогу під час формування розташовувати елементи обох матриць на місці матриці А. Одиничну діагональ матриці U в масив А не записуємо. 2. Перший стовпець матриці А збігається з першим стовпцем L, отож, його залишаємо без змін, тобто /,, = аі Х, і = 1..N. 8 7-451
226 3.3. Метод L{/-перетворення а\і 3. Перший рядок матриці U формуємо так: аХі-——, ’ аі.і i = 2,...,N. 4. У циклі з параметром який змінюється від 2 до N, виконуємо наступне: i-i • ak,i = ak,i~^ak,j'aj,i ’ Внутрішнім ЦИКЛОМ ПО /=1 к = - формуємо к-й стовпець матриці L; /-і ° /,k~^2la u j'a j,k j=1 • аік = , внутрішнім циклом по аи к = i + l9...9N - формуємо к -й рядок матриці U . 5. Закінчення процедури Decomp. Її вихідними параметрами є перетворена матриця J і значення параметра change. У процедурі Solve виконуємо такі кроки: 1. Оскільки ми переставляємо рядки матриці А системи (3.2.3), то необхідно здійснити аналогічну перестановку елементів вектора b . З цієкЗ метою аналізуємо і використовуємо значення вхідного параметра change. 2. Перший елемент вектора у є таким: у х . У процедурі аіЛ значення вектора у записуємо на місце вектора Ь . і-і 3. Формуємо вектор у: уі = (у-'^аі j-yi)/ajJ,.i = 2,...,N. /=і 4. xN = yN. 5. Виконуємо зворотний хід методу Гауса: N %_,• = Ум-і ~ X aN-t.j’ Xj » * = l’-’N ~1 • j=N-.i+1 6. Закінчення процедури Solve. Вихідний її параметр - вектор розв’язку х.
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 227 3.3.2. Процедура Decomp Procedure Decoxnp (Var A: Matrix; N: Integer; Var Change : Integer) ; Var і, j, k : Integer; R : Real; Begin Change := 1; R := Abs (A[l, 1] ) ; For j := 2 to N do If Abs (A[j, 1] ) >= R then Begin Change := j ; R := Abs (A[ j, 1] ) End; If R <= IE-7 then Begin Write (' Система вироджена '); Repeat Until KeyPressed; Halt End; If k <> 1 then Begin For і := 1 to N do Begin R := A [ Change, і ] ; A[Change, i] := A[l, i] ; A[1, i] := R End End; ' For і := 2 to N do A[l, і] := A[ 1, i] / A[l, 1]; For і := 2 to N do Begin For k := і to^K^o Begin R := 0; For j := 1 to і - 1 do R := R + A[k, j] * A[j, i]; A[k, i] := A[k, i] - R End; If Abs ( A[i, і] ) <=lE-7 then Begin Writeln ('Система вироджена ); Repeat Until KeyPressed; Halt End;
228 3.3. Метод L{/-перетворення For к := i + 1 to И do Begin R := 0; For j := 1 to ± - 1 do R := R + A[i, j] * A[j, k]; A[i, k] := ( A[i, k] - R ) / A[i, i] End End End; 3.3.3. Процедура Solve Procedure Solve (A : Matrix ; Var b, x : Vec ; N : Integer) ; Var i, j : Integer; R : Real; Begin If Change о 1 then Begin R := b[Change]; b[Change] := b[l]; b[l] := R End; b[1] := b[1] / A[ 1, 1]; For i := 2 to N do Begin R := 0; For j := 1 to i - 1 do R := R + A[i, j] * b[j]; b[i] := ,( b[i] - R ) / A[i, i] End; x [N] := b [N]; For i := 1 to N - 1 do Begin R := 0; For j := N + 1 - i to N do R := R + A[N - i, j] * x[j]; x[N - i] := b[N - i] - R End End; Change, Для системи четвертого порядку матриця J набуде такого вигляду:
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 229 М1,2 «1.3 «1.4 «1.2 «1.3 «1,4 «1.1 ; ■■ *1,1 «1.1 ’’ «1.1 « 2,1 ^2,2 ; *2,2“ «2,1 ‘«1,2 : «2,3 «2,3“ «2,1 *«1,3 «2.4 « 2,4 «2,1 ' «1,4 | «2,2 «2,2 'з, ^3,2 /з,з ■. «3,4 «3,1 «3,2“ «3,1 ‘«1,2 « 3,3 («3,1 ■ «1,3 «3,2 ' «2,3 ) , « 3,4— («3,1 ' «1,4 + «3,2 ' «2,4 «3,3 /4.1 кг '4.3 ^4,4 «4,1 «4,2~ «4,1 '«1,2 «4,3 («4,1 '«1,3 +«4,2 -«2,з) «4,4—(«4,1 ‘«1,4 +«4,2 ’«2,4 "*"«4,3 ‘«3,4) Матриця тестової СЛАР, N = 4. А[1,1]:=0.0; А[1,2]:=5.6; А[2,1]:=3.8; А[2,2]:=5.1; А[3,1]:=4. 1; А[3,2]:=5.7; А[4,1]:«1.1; А[4,2]:=2.7; Її права частина: В[1]:=17.2; В[2]:=12.5; В[3]:=18.8; В[4]:=12.5; Матриця І_и-та1:гіх і_и І_ІІ і_и А[1,3]:=7.8; *11,*}:=3.8; А[2,3]:=2.8; А[2,4]:=0.8; А[3, 3]:=7.2; А[3,4]:=1.8; А[4,3]:—7.З; А[4,4]:-1.4; [1, 1] =4.1000 LU [1,2]=1.3 902 [2,1]=3.8000—Ьи [2,2] =-0.1829 0000 1000 1-11 [3,21 Ьи [4,2] »5.6000 «1.1707 1.11 [1,3]=1.7561 І_и І_1) [2,3]=21.1733 І_и І_и[3, 3]=-110.7701.и іи [4,3 ] =-19.42001.1) [3.1]=0. [4.1]=1. Розв’язок: Х[1] :=1.0; Х[2] :=1.0;х[3] :=1.0; Х[4] :=1.0;. ’1,4] =0.43 90 - 7467 2057 6460 1 у J “І/ ■ 4« '2.4І-4.7“ 3,4І=0.2С 4,4]--0.« Завдання для самостійної роботи Написати головну програму і дослідити роботу наведених вище процедур на тестових прикладах.
230 3.3. Метод Ь{/-перетворення 3.3.4. Обумовленість матриць Застосовуючи чисельні методи для розв’язання фізичних задач, необхідно розрізняти властивості задачі і властивості чисельного алгоритму, використаного щодо її розв’язання. Математики стверджують, що задача поставлена коректно, якщо її розв’язок існує, якщо він єдиний і якщо він неперервно залежить від вхідних даних. Останнє твердження називають стійкістю щодо вхідних даних. Коректність вихідної фізичної задачі зовсім не гарантує добрих властивостей обраного нами чисельного методу її розв’язання. Отож, для коректно поставлених задач властивості чисельних методів необхідно вивчати додатково [102]. Коротко розглянемо коректність розв’язання СЛАР вигляду А • х = Ь , де А - квадратна матриця розміру (/V х /V) . Вище цю систему позначено як (3.1.1). Відомо, що для кожного //-вимірного вектора розв’язок задачі (3.1.1) існує тоді і тільки тоді, коли сієї А Ф 0. У такому випадку існує обернена матриця А~1 і розв’язок (3.1.1) можна записати так: х = А~1-Ь. (3.3.1) Щоб переконатись у коректності задачі (3.1.1), необхідно встановити неперервну залежність її розв’язку від вхідних даних. Виникає два питання: що таке вхідні дані задачі (3.1.1) і що таке їхня неперервна залежність? На перше запитання відповідь є такою: вхідними даними є вектор Ь і матриця А . Відповідно, розрізняють стійкість по правій частині (збурюється Ь , А - постійна) і коефіцієнтна стійкість (збурюється А, Ь - постійна). Нас цікавить, як може змінитись розв’язок х у результаті незначних змін елементів вектора Ь . Отже, маємо 2 системи: А-х -Ь і А-х = Ь. Введем позначення: Зх = х-х і 8Ь-Ь-Ь . Кажуть, що система (3.1.1) є стійкою по правій частині, якщо за будь-яких Ь і Ь справедливе оцінювання: (3.3.2) де Мх>0 - стала, яка не залежить від Ь і Ь . Це оцінювання засвідчує, що ||Лс|| —» 0 при ||<5&|| —» 0 . Виконання такої залежності є
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 231 дуже важливим, оскільки рідко вдається задати Ь точно внаслідок існування похибок заокруглення. Якщо сІеїЛ^О, то систему (3.1.1) називають стійкою по правій частині, і з (3.3.1) випливає: іЖК'Іиі- <3 3 3> Зауважимо, що чим ближчим до 0 є визначник матриці А, тим стала М, буде більшою і тим більше похибка Ь спотворить розв’язок х. Вираз (3.3.2) налічує абсолютні похибки. Якщо * N1 • ІНІ переити до відносних похибок |7игї| і \то можна отримати N N оцінювання відносної похибки розв’язку системи (3.1.1) через відносну похибку правої частини. Для цього використаємо рівність, яка випливає з (3.1.1): Ж4ІИ <3-3-4> Перемножуємо (3.3.3) і (3.3.4). Отримаємо: ни А- .ІЛІМ (3.3.5) А 1 МиіІ називають числом обумовленості мат- и Число М = риці А . Воно характеризує чутливість розв’язку х до малих змін елементів Ь . Якщо значення М велике, матриця А - погано обумовлена. М володіє властивостями: • М> 1; * М ~ ’ ДЄ ‘ Лпіп(^) ~ ВІДПОВІДНО, найбільше і найменше за модулем власні значення матриці А. Для методу Гауса, при використанні його на ЕОМ з мантисою дійсного числа, яка має число розрядів ї, відносну похибку розв’язку х системи (3.1.1) обчислюють за формулою: И«д/-ЛГ-2"г, N де N - розмір системи (3.1.1).
232 3.4. Розв’язування систем нелінійних рівнянь 3.4. Розв'язування систем нелінійних рівнянь Необхідність розв’язування систем нелінійних алгебричних чи трансцендентних рівнянь (СНР) виникає в багатьох задачах фізики і техніки [75]. У векторній формі ці системи записують так: ВД = 0, (3.4.1) де X = (х1,х2,...,хИ)Т є вектор N невідомих, Р = (/1,/2,...,/м)т, N -вимірний вектор значень функції. Подамо координатний запис системи (3.4.1): /і{х1,х2,...,х„) = 0 /2(х1,х2,...,хЛГ) = 0 Нелінійні системи рівнянь розв’язують ітераційними методами. Ці методи є суто локальними, тобто вони працюють тільки за правильного вибору початкового наближення. Зазначимо, що хороше початкове наближення не завжди є близьким до шуканого розв’язку. Найпростішим ітераційним методом розв’язання системи (3.4.1) слугує метод простої ітерації. Одним із найпотужніших є метод Ньютона. * 3.4.1. Метод простої ітерації Опишемо спочатку шлях побудови методу простої ітерації. Додамо до рівняння (3.4.1) зліва і справа вектор X . Х + Р(Х) = Х. З цього виразу легко утворити необхідний ітераційний процес: Умова збіжності цього процесу до розв’язку системи (3.4.1) задається відповідною теоремою. Теорема. Нехай X* є розв’язком системи (3.4.1). Якщо в околі {/д;ґ) = фг-х*| < г} вектор-функція Ф{Х) задовольняє умову Коші-Ліпшиця (тобто для будь-яких Х\ X" є ІІГ(Х*)
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 233 справджується ||Ф(ЛГ')-Ф(ЛГ")|^^||ЛГ'-ЛГ'Г|| з постійною <7 < І), то послідовність Хк при Хк & иг{Х*) збігається до розв’язку X* і збіжність оцінюється виразом: || Хк- X* || < цк |х° - X* ||. Приведену в теоремі умову Коші-Ліпшиця здебільшого достатньо складно довести, отож, на практиці як достатній критерій ібіжності використовують іншу умову, аналогічну умові |ф'(х)| < 1 для одного рівняння. 3.4.2. Метод Ньютона Припустимо, що система (3.4.1) має принаймні один розв’язок, тобто існує такий вектор X*, підстановка якого у кожне з рівнянь системи перетворює це рівняння на тотожність. Головна ідея методу Ньютона полягає у вилученні з рівнянь (3.4.2) лінійних частин, які є головними за малих приростів (збурень) аргументів. Такий крок дає змогу звести початкову задачу до розв’язання послідовності лінійних систем. Метод Ньютона для N рівнянь можна застосувати тільки тоді, коли можна обчислити всі частинні похідні функцій за змінними хі. Позначимо через Л(Х) матрицю частинних похідних вектора F по змінних X. Таку матрицю називають матрицею Якобі. Її (/, у) -м елементом є значення похідної д/і * Т & —- у точці х , тобто оа = —-. ску дХ] З метою побудови формули ітераційного процесу Ньютона лінеаризують Р{Х) в околі точки ЛГ(0), яку називають точкою початкового наближення. Лінеаризацію здійснюють, розкладаючи Р(Х) в рядЛейлора і враховуючи лише перші два члени розкладу: Р(Х) * F(X(0)) + ЩХт)-(X -Х(0)) . (3.4.3) З метою обчислення наступного наближення Х(1) до розв’язку системи (3.4.1), розв’яжемо рівняння ^(Х(0)) + Уа(Х(0)КХ-Х(0)) = 0 щодо вектора X. Позначаючи його через Х(1), одержимо:
234 3.4. Розв’язування систем нелінійних рівнянь Хт = Х(0) - Уа_1(Х(0))^(Х(0)), (3.4.4) де - обернена матриця Якобі, обчислена для значення Хт. Узагальнюючи вираз (3.4.4), отримаємо шукану формулу ітераційного методу Ньютона: *(*♦!> =Х№)(3 4 5) У формулі (3.4.5) символом к позначено номер ітерації. У дужки ми його взяли для того, щоб відрізнити номер від операції піднесення до степеня. Збіжність ітераційного процесу (3.4.5) доводять за теоремою Дж. Форсайта [102], яку сформулюємо на рівні ідеї. ♦ Нехай X є розв’язком системи (3.4.1). Для цього розв’язку матриця Якобі Л(Х ) не є виродженою, і другі частинні похідні функції Р є неперервні поблизу розв’язку X*. Якщо наближення Х(°) є достатньо близьким до X*, то ітерації Ньютона, задані виразом (3.4.5), будуть збіжними. Позначимо через = Х^ -X* - похибку розв’язку системи (3.4.1) на к-й ітерації. Тоді при коо відношення (Аг)|| буде обмеженим, тобто ітераційний процес (3.4.5) матиме квадратичну швидкість збіжності. Як і в одновимірному випадку, тут головна проблема полягає у вдалому виборі початкового наближення Х(0), яке бажано вибрати достатньо близьким до розв’язку, щоб відбулася швидка збіжність. На практиці таке наближення досягають двома шляхами: якщо пощастить вдало обрати Х(0), або шляхом наполегливості дослідника, який дає змогу алгоритмові виконувати дуже багато ітерацій до того, як процес почне швидко збігатися. Ітераційний метод Ньютона у формі (3.4.5) для розв’язання систем (3.4.1) використовувати не доцільно, оскільки обертання матриці Якобі є процедурою, з погляду кількості арифметичних операцій, доволі громіздкою. На практиці формулу (3.4.5) заміню¬
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 235 ють двома виразами, що дає змогу замінити процедуру обертання матриці Якобі процедурою Гауса для розв’язання СЛАР. Отож, введемо позначення: Ох(к) = .АГ1 (Х{к)) • F(XW):' (3.4.6) Вектор Охік) називають вектором нев’язки. Домножуючи вираз (3.4.6) зліва і справа на матрицю ^(Х(к)), отримаємо: /а (Х^)-Ох^ = Р(Хт) . (3.4.7) Вираз (3.4.7) є системою лінійних алгебричних рівнянь щодо вектора невідомих £>х(Аг) . Розв’язавши цю систему методом Гауса, використаємо її розв’язок в ітераційному процесі Ньютона: Х^=Х^-0^ (348) Процес вважатимемо закінченим, якщо |лг(Аг+1* - = Dx (Аг) < Eps, де Eps - задана нами точність обчислень. 3.4.3. Алгоритм методу Ньютона Сформулюємо кроки алгоритму розв’язання СНР методом Ньютона: 1. Задаємо і вводимо значення таких параметрів: • N - розмір системи (3.4.1). • Eps - необхідна точність обчислень. • Константа Ктах - максимально допустима кількість ітерацій. Якщо за Ктах ітерацій розв’язок не знайдено, процес обчислення розв’язку припиняємо і друкуємо повідомлення про те, що за задану кількість ітерацій розв’язок із необхідною точністю знайти не вдалось. 2. Вводимо вектор початкових умов Х(0). 3. Зашикаємо ітераційний цикл за змінною k = L.Kmax. У цьому циклі: • обчислюємо вектор F процедурою FM ; • обчислюємо матрицю Якобі Ja процедурою JAC ; • знаходимо вектор Dx, розв’язуючи систему (3.4.7) процедурою GAUSS;
236 3.4. Розв’язування систем нелінійних рівнянь • виконуємо ітерацію Ньютона: х^к+У) - X^ , циклом по компонентах вектора X; • у цьому самому циклі визначаємо норму вектора Ох, як значення модуля його максимальної компоненти: ОхМдх = ||Лх(<г)|| = шах (|ях(*>|); • якщо ЭхМах < ЕрБ, розв’язок X вважаємо знайденим, друкуємо його і завершуємо роботу програми. Якщо ця умова не справджується - виконуємо наступну ітерацію, тобто повертаємо управління на початок нашого циклу. 4. Якщо за задане число Ктах ітерацій збіжності не досягнуто, друкуємо щодо цього відповідне повідомлення і завершуємо роботу програми. Блок-схему наведеного вище алгоритму подано нарис. 3.4. Під час реалізації нашого алгоритму виникає закономірне питання з приводу способу обчислення матриці Якобі. Якщо обчислення похідної функції вже в одновимірному випадку є непростою задачею, то для системи N рівнянь обчислення Л(Х) значно трудомісткіше, ніж обчислення Р(Х). Звичайно, розв’язуючи автономно нашим алгоритмом нескладну СНР, можна обчислити матрицю Якобі вручну, описуючи двовимірний масив і присвоюючи кожному його (/,7 )-му елементові вирази відповідних похідних я/* —- . Це буде надто громіздким і не універсальним процесом. дх; На практиці елементи матриці Якобі визначають чисельно, виходячи з означення похідної: Уі _ /і(*1 +&*2у- >*Л/)-/і(*1>*2> ">%). _ /і(*1>*2 +6>->%)-/і(*1>*2>">*Лг) З*, Q ’дЛг <2 _ /г(^ +<2,*2>-- >%)-/2(*1>*2>- -,*Лг). Тут <2 - малий приріст змінної (збурення), який доцільно вибирати таким: О = • Зауважимо, що оптимальне, для кожної функції, значення 0, обрати непросто, отож, інколи матриця Якобі, обчислена таким способом, може виявитись близькою до виродженої.
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 237 3.4.4. Блок-схема алгоритму Ньютона
238 3.4. Розв’язування систем нелінійних рівнянь 3.4.5. Реалізація алгоритму методу Ньютона На практиці популярними є так звані квазіньютонівські методи, які починаються з дуже важких початкових ітерацій, однак з наближенням до розв’язку їхня точність зростає. Ці методи широко використовують в задачах багатовимірної оптимізації. Вичерпну інформацію щодо розглянутих методів подано у праці Оргеги, Рейнболда [75], яку можна вважати довідником з методів розв’язання СНР. Процес обчислення елементів матриці Якобі можна виконати за такою процедурою: Procedure JAC (Var Ja: Matrix; X: Vec; Q: Real; N: Integer) ; Var i, j : Integer; Fp : Vec; {вектор функції від збуреної і-ої компоненти змінної X } Begin Q := Eps / 1000.0; EM (F, X, N); {обчислення вектора функції F від незбуреної змінної X } For j:=1 to N do Begin X[j] :=X[j] +Q; {збурення j-ої компоненти вектора X} EM (Fp, X, N);{обчислення вектора функції Fp від збуреного вектора X } For і:=1 to N do Ja[і, J] := (Fp[i] - F[і]) / Q;{обчислення (i,j)- компоненти матриці Якобі } X[j] := X[j] - Q {зняття збурення j-ої компоненти вектора X} End End;
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 239 Тестова система трьох нелінійних рівнянь з трьома невідомими (N=3): fx (*і, х2, ) = хх + е4 1 + (х2 + х3 / - 27 = 0 /г(х\>х2<хъ) = х\ -є*2'2 +Х32 -10 =0. f3(xl,x2,x3) = x3+Sm(x2-2) + x^ -7=0 Цю систему запрограмуємо у формі процедури з назвою FM: Procedure EM( Var F: Vec; X:Vec; N: Integer); Begin F[l]:=x[l] + Exp (x[l]-l)+(x[2]+x[3])*(x[2]+x[3])-27; F[2]:=x[l] * Exp (x[2] - 2) + x[3] * x[3] - 10; F[3]:=x[3] + Sin (x[2] - 2) + x[2] * x[2] - 7 End; За початкових умов: розв’язку X* = (x} 9x29x3): JC,° = 0.75; x2 =1-5; x°3 =4.0, x, = 1.0; X2 = 2.0; x3 = 3.0 одержимо шукании вектор Якщо задати точність Еря = 0.0001, розв’язок отримаємо за 11 ітерацій. Підставляючи обчислені значення у нашу тестову систему, переконаємось, що кожне з її рівнянь перетворюється у тотожність.
240 3.5. Модулі (Units) 3.5. Модулі (Uni t) Середовище BP забезпечує програмісту доступ до значної кількості стандартних (вбудованих) констант, типів даних, змінних, процедур і функцій. У своїй програмі ми надто рідко використовуємо їх усіх водночас. Отож, їх розділено на логічно пов’язані групи, так звані модулі (Unit), що дає змогу використовувати в програмі тільки те, що необхідно у певній ситуації. Механізм модулів дає змогу розділяти програму на окремі частини, розробляти ці частини колективом програмістів, компілювати їх окремо, а потім об’єднувати все це в один великий програмний комплекс. Програмні модулі, як набори констант, типів даних, змінних, процедур і функцій, можна спільно використовувати у декількох програмах. Структура модуля є подібною до структури окремої PascaZ-програми. Проте він, на відміну від головної програми, окрім базового набору операторів, який викликається багаторазово, може мати набір операторів одноразового виконання (розділ ініціалізації), який перед першим запуском програми здійснює необхідні одноразові дії, наприклад, вмикання графічного режиму, ініціювання файла. Інша причина необхідності використання модулів у великих програмах полягає в обмеженнях кодового сегмента прикладної програми. Процесори Intel 80x86 (і споріднені з ними) у реальному режимі їхньої роботи обмежують розмір сегмента коду 64-ма кілобайтами. Це означає, що головна програма не може перевищувати 64Кб. Borland Pascal в процесі компілювання для кожного модуля створює окремий сегмент коду, що дає змогу обходити бар’єр 64Кб. ВР надає програмістові доступ до деяких стандартних модулів, таких як System, Crt та ін. Вони розташовані у стандартній бібліотеці середовища - файлі Turbo.tpl й автоматично завантажуються при кожному запуску середовища ВР. Будь-яка програма може використовувати кожну із процедур і функцій, які є в цих модулях, що знімає потребу кожен раз “винаходити велосипед”. Окрім бібліотеки Turbo.tpl, стандартні модулі містяться в інших бібліотеках середовища ВР, наприклад, графічні засоби зосереджені в окремій бібліотеці-модулі GraphJpu.
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 241 3.5.1. Структура модуля Хоча модуль за своєю структурою подібний на головну програму, проте він має з нею декілька істотних розбіжностей. У загальноприйнятих позначеннях модуль має структуру: Unit <ім'я>; Interface [Uses ссписок модулів, що розділені комами>;] < Розділ глобальних описів змінних> < Розділ заголовків процедур і функцій> Implementation [Uses ссписок модулів, що роділені комами>;] % < Розділ локальних описів змінних> < Розділ реалізації процедур і функцій> Begin < Оператори ініціалізуючої частини модуля> End. Як бачимо, заголовок модуля розпочинається зарезервованим словом Unit, за яким є ім’я модуля (ідентифікатор). Наступним елементом модуля є ключове слово Interface. Воно позначає початок інтерфейсної секції модуля - частини, доступної всім іншим модулям або програмам, які його використовують. Програмний модуль може сам використовувати інші модулі, які для цього визначаються в операторі Uses. Цей оператор, якщо він потрібний, може перебувати у двох місцях: • відразу після ключового слова Interface; у цьому випадку будь-які константи і типи даних, описані в інтерфейсній секції цих модулів, можуть використовуватися в будь-якому описі в інтерфейсній частині зазначеного модуля; • за ключовим словом Implementation; у цьому випадку всі описи з цих модулів можуть використовуватися тільки в секції реалізації. 3.5.2. Інтерфейсна секція (Interface) Інтерфейсна секція є “загальнодоступною” частиною модуля. Вона розташована між зарезервованими словами Interface та Implementation і визначає елементи, “видимі” (доступні) для будь- якої програми (або модуля), що використовує цей модуль.
242 3.5. Модулі {Units) В інтерфейсній частині (секції) модуля можна визначати константи, типи даних, змінні, процедури і функції. Як і в головній програмі, їх можна розташовувути у будь-якому порядку, а самі секції можуть траплятися кілька разів (інаприклад, програма може містити секцію Var, за якою слідує секція Const, а потім інша секція Var). Процедури і функції, призначені бути видимими для будь-якої програми, яка використовує цей модуль, описуються в секції інтерфейсу шляхом лише перерахування усіх заголовків процедур і функцій. Реалізації програмної логіки зазначених в інтерфейсі процедур і функцій (тіла підпрограм) містяться у наступній секції. 3.5.3. Секція реалізації (Implementation) Ця секція є “приватною” частиною модуля. Вона починається зарезервованим словом Implementation. Все, що описане в секції інтерфейсу, є видимим в секції реалізації: константи, типи, змінні, процедури і функції. Окрім цього, в секції реалізації можуть бути свої додаткові описи, які є невидимими для програм, що використовують цей модуль. Програма не знає про їхнє існування і не може посилатися на них або звертатися до них. Проте ці приховані елементи можуть використовуватися (і, зазвичай, використовуються) “видимими” процедурами та функціями, тобто тими підпрограмами, чиї заголовки подано в секції інтерфейсу. Оператор Uses може перебувати в секції реалізації і повинен безпосередньо бути за ключовим словом Implementation. Описи процедур і функцій, заголовки яких подано в інтерфейсній секції, у секції реалізації повинні мати ті самі заголовки, проте останні можна записувати у скороченій формі: тільки ключове слово Procedure або Function та ім’я (ідентифікатор) цієї підпрограми. Далі підпрограма повинна містити всі свої локальні описи (мітки, константи, типи, змінні і вкладені процедури та функції), за якими розташована операторна частина (тіло) самої підпрограми. Підпрограми, що є локальними для секції реалізації (тобто не описані в секції інтерфейсу), повинні мати детальний (не скорочений) заголовок.
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 243 3.5.4. Секція ініціалізації Зазвичай, уся секція реалізації модуля знаходиться між зарезервованими словами Implementation і End. Проте, якщо перед End помістити зарезервоване слово Begin, а між ними - оператори, то такий складений оператор стає секцією ініціалізації модуля (Initialization). Ця секція є місцем, де ініціалізуються структури даних (змінних), які використовує програмний модуль або які він робить доступними програмі, що використовує цей модуль. Таку секцію, наприклад, можна використовувати для відкриття файлів, які програма застосовує в процесі усієї роботи. Під час виконання програми, яка використовує цей модуль, секція ініціалізації модуля активізується перед запуском основного тіла програми. Якщо програма використовує більше одного модуля, то секції ініціалізації всіх модулів активізуються (у порядку, зазначеному в операторі Uses у програмі) перед тим, як виконати основне тіло програми. 3.5.5. Використання модулів Прикладна програма використовує модулі, що зберігаються в уже відкомпільованому стані, тобто у двійковому представленні машинного коду. Навіть інтерфейсна секція зберігається у спеціальному двійковому форматі таблиці ідентифікаторів, який використовує Borland Pascal. Отож, використання підпрограм як модулів пришвидшує процес компілювання головної програми під час її налагодження. Двійкова форма представлення підпрограм унеможливлює також несанкціоноване внесення змін у готову підпрограму. Зміни може вносити тільки той, хто має доступ до вихідного тексту модуля. Як зазначено раніше, для під’єднання нового модуля або набору модулів до програми необхідно на початку програми помістити оператор Uses, після якого подати список розділених комою імен тих модулів, які необхідно використати. Наприклад\ Program My_Prog; Uses ThisUnit, ThatUnit, OtherUnit; Коли компілятор натрапляє на такий рядок Uses, він додає інформацію з секції інтерфейсу кожного модуля до таблиці
244 3.5. Модулі (Units) ідентифікаторів і приєднує машинний код, представлений в секції реалізації, до самої програми. Модулі приєднуються до таблиці ідентифікаторів у порядку їхнього розташування в Uses. Зауважимо, що порядок запису модулів в операторі Uses значення не має. Якщо модуль ThisUnit використовує Thatunit, або навпаки, можна описати їх у будь-якому порядку, а компілятор визначить, який модуль потрібно скомпонувати з програмою My_Prog першим. Фактично, якщо модуль ThisUnit використовує Thatunit, але My_Prog не активізує безпосередньо жодну з підпрограм у модулі Thatunit, Ви можете “приховати” підпрограми модуля Thatunit, тобто вилучити його в операторі Uses: Unit ThisUnit; Uses Thatunit; Program My_Prog; Uses ThisUnit, OtherUnit; У нашому прикладі модуль ThisUnit може активізувати будь-яку підпрограму модуля Thatunit, а програма My_Prog може активізувати будь-яку з підпрограм модуля ThisUnit або OtherUnit. Проте програма My_Prog не може активізувати підпрограми модуля Thatunit, оскільки Thatunit не зазначено в операторі Uses програми My_Prog. Якщо у програмі не подано рядка Uses, Borland Pascal у будь- якому випадку приєднає стандартний модуль System. Цей модуль забезпечить виконання багатьох стандартних підпрограм середовища UP. 3.5.6. Створення власних модулів Якщо одну чи кілька підпрограм написано і цілковито налагоджено, доцільно оформити їх як модуль згідно з правилами, описаними вище. Після цього необхідно зберегти текст модуля на диску під тим іменем, яке зазначене в заголовку модуля Unit <ім ’я>. Розширення цього текстового файла - pas (як і будь- якого іншого файла, який створюється редактором середовища ВР). У цьому файлі може міститися тільки один модуль. Щоб скомпілювати модуль, достатньо натиснути клавішу [F91. Звичайно, компілювання також відбудеться, якщо використати
3. РОЗВ’ЯЗУВАННЯ СИСТЕМ РІВНЯНЬ 245 альтернативу текстового меню середовища СотріІе\Маке. Якщо наш модуль не містить синтаксичних помилок, то буде створено двійковий файл <ім'я>Хри і записано у директорію, зазначену у першому рядку діалогового вікна, яке відкривається при виборі альтернативи Options\Directories. Цей рядок позначено підписом EXE & TPU Directory. У випадку, якщо цей рядок є порожнім, tpu-файл запишеться у поточний каталог, де є текст модуля. З метою використання новоствореного модуля його під’єдну- ють до програми у рядку Uses <ім’я>. У цьому випадку файл модуля повинен бути або у поточному каталозі, або у каталозі бібліотек середовищаВР, розташованому по шляху ..\ВР\UNITS. Якщо наш модуль є настільки важливим, що його доцільно записати у системну бібліотеку Turbo.tpl, то після запису для підключення до програми зазначати його <ім’я> у рядку Uses не потрібно. Пересилання власних модулів у бібліотечний файл стандартних модулів виконує стандартна утиліта середовища ВР з назвою TPUMOVER.ехе. Цю утиліту використовують також для вилучення зайвих модулів з бібліотечного файла Turbo. tpl9 завдяки чому зменшується його розмір і кількість пам’яті, необхідної для його завантаження. Примітка: якщо підпрограми використовують масиви, структуру яких задано за посередництвом опису власних типів Туре, то ці описи необхідно обов’язково розташовувати в інтер-: фейсній частині нашого модуля, а не в описовій частині головної програми, яка використовуватиме модуль. За наявності дублюючих структур Туре в головній програмі і в модулі, з головної програми їх необхідно вилучити. Приклад. Існує процедура розв’язання систем лінійних алгебричних рівнянь методом Гауса. Необхідно оформити цю процедуру як модуль. Подаємо фрагмент процедури методу Гауса: Procedure GAUSS (A:Matrix; B:Vec; N: Integer; Var X:Vec) ; Var і, j, k : Integer; R : Real; Begin If N = 1 then {Оператори процедури GAUSS } For j := і + 1 to N do R := R - A[i, j] * X[j];
246 3.5. Модулі (Units) Х[і] := R End End; Описи власних типів Matrix і Vec, які ми бачимо у заголовку процедури, розташовано у головній програмі, яка активізує цю процедуру. Її фрагмент подано нижче. Program Gol_Pr_Xio; Uses Crt; Type Matrix = Array [1. .5, 1. .5] of Real; Vec = Array [1..5] of Real; Var A : Matrix; X, В : Vec; Назвемо наш модуль Gau_mod. Початок і завершення його буде таким: Unit Gaujnod; Interface Uses Crt; Type Matrix = Array [1..10 , 1..10] of Real; Vec = Array [1..10] of Real; f Procedure GAUSS (A: Matrix; В: Vec; N -.Integer; Var X: Vec) ; Implementation ■■ Procedure GAUSS; Var і, j, k : Integer; R : Real; Begin If N = 1 then { Оператори процедури GAUSS } For j := і + 1 to N do R := R - A[i,j] * X[j] ; End END. Початок головної програми, яка викликатиме наш модуль, матиме вигляд: Program Gol_Pr_Xio ; Uses Crt, Gau_mod; Var A ; Matrix; X, В ; Vec;
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ Під візуалізацією розуміємо відображення на графічному екрані процесів різної природи: графіків експериментальних результатів і результатів їхньої обробки, результатів моделювання фізичних процесів і систем, гістограм та діаграм тощо. Найпростішим варіантом візуалізації слугує лінійка прогресу - прямокутник, відсоток заповнення якого прямо пропорційний до частини виконання певної операції. Маючи перед очима цю лінійку і спостерігаючи за її динамікою, ми можемо оцінити об’єм невиконаних операцій у поточний момент часу. Проте виведення поточного числа зі знаком “X ” не є візуалізацією. 4.1. Графічне середовище ВР Цей розділ доповнює інформацію про програмування графічного режиму у середовищі ВР, яку подано у параграфі 2.5.4. Окрім довідкової інформації, розділ містить алгоритми і програми застосування графічних можливостей середовища ВР для розв’язання практичних задач. 4.1.1. Установлення роздільної здатності екрана S SetGraphMode (GraphMode) ; • Змінна GraphMode належить до типу Integer. Її можливі значення подано в табл. 4.1.
248 4.1. Графічне середовище BP Таблиця 4.1 Значення змінної GraphMode Установлена роздільна здатність екрана 0 640 х 200 1 640 х 350 2 640 х 480 Під час ініціалізації графічного режиму за замовчуванням, тобто за умови використання режиму Detect, встановлюється роздільна здатність екрана VGA (640 * 480). Зниження роздільної здатності екрана може знадобитися, наприклад, для узгодження роздільної здатності з різними графічними пакетами. 4.1.2. Очищення графічного екрана S ciearJDevi.ee; - очищає та ініціалізує графічний екран. S ClearViewPort; - очищає обмежену область перегляду. 4.1.3. Установлення кольорів S SetBkColor (BackColor); - встановлює колір тла (фону). • Параметр BackColor (тип Word); - колір тла. S SetColor (Color) - встановлює колір графічних об’єктів, які заплановано вивести на екран; • Параметр Color (тип Word) - колір графічних об’єктів. Кольори можна задавати або цифрою або їхньою англійською назвою (табл. 4.2). ' Таблиця 4.2 Темні кольори Світлі кольори Можливі значення параметра Color та BackColor Назва кольорів Можливі значення параметра Color та BackColor Назва кольорів 0 Black Чорний 8 DarkGray Темно-сірий 1 Blue Синій 9 LightBlue Світло-синій 2 Green Зелений 10 LightGreen Світло-зелений 3 Cyan “Морська хвиля” 11 LightCyan Світла “морська хвиля” 4 Red Червоний 12 LightRed Світло-червоний 5 Magenta Фіолетовий 13 LightMagenta Світло- фіолетовий 6 Brown Коричневий 14 Yellow Жовтий 7 LlghtGray Світло- сірий 15 fthlte Білий
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 249 Якщо задати однакові значення параметрів Color та BackColor, то малюнок буде невидимим, що часто використовують за необхідності стерти частину зображення, яке є на графічному екрані, наприклад, під час програмування рухомих зображень. 4.1.4. Виведення піксела на екран S PutPixel (X, Y, Color); - виводить піксел на графічний екран. • Параметри х, У - координати піксела (тип Integer). • Параметр Color - колір піксела (тип Word) задається за вшценаведеною таблицею 4.2. 4.1.5. Виведення ліній на екран Цю операцію можливо виконати трьома способами: • між двома точками на графічному екрані; • від поточної позиції графічного курсора до певної точки екрана; • від курсора до точки, зміщеної на декілька пікселів по горизонталі і (або) по вертикалі. S Line (XI, її, Х2, Y2)проводить лінію з точки, яка має координати (XI, Y1) , у точку з координатами (Х2, Y2). S LineRel (DX, DY); - лінія простягається з поточної робочої точки на величину DX по осі х і DY по осі Y. Значення DX та DY задають у пікселах. S ІіпеГо (X, Y); — лінія простягається з поточної позиції графічного курсора в точку з координатами (X, Y). Тип усіх аргументів у процедурах, які наведено вище - Integer. Колір ліній попередньо задають процедурою SetColor (Color);. 4.1.6. Переміщення графічного курсора S MoveRel (DX, DY); - переміщає невидимий графічний курсор на величину DX пікселів по осі х і, відповідно, на величину DY по осі Y без малювання. S MovsTo (х, Y)переміщає графічний курсор з поточної позиції курсора в точку з координатами (х, Y) без малювання.
250 4.1. Графічне середовище BP 4.1.7. Виведення ламаних і багатокутників •S Rectangle (XI,Yl, Х2 ,Y2)виведення прямокутника зі сторонами, паралельними осям координат. Тут (XI, Y1) і (X2,Y2) - координати, що визначають лівий верхній і правий нижній кути прямокутника (тип Integer). 'S Bar3D (XI, Yl, X2, Y2, Depth, Top); - виведення тривимірного паралелепіпеда. • Величини XI, Yl, Х2, Y2 мають такий самий зміст і тип, що й при виведенні прямокутника; • Depth - глибина (тип Word), яка найчастіше дорівнює половині вузької сторони передньої грані паралелепіпеда; • Тор - ознака видимості тривимірної вершини (тип Boolean). Якщо Тор=Ггие - вершина є видимою. Якщо ж Top=False - вершина невидима (використовується при постановці на рисунку одного паралелепіпеда на інший); S DrawPoly (PixNumb, VertCords)виведення ламаної і багатокутника. • На екран вив0диться ламана лінія, що з’єднує точки, число яких є PixNumb (тип Word). • Координати точок задають у масиві VertCords, який необхідно описати так: Var VertCords : Array [ 1..2*PixNumb ] of Word; . Цей масив містить інформацію щодо екранних координат вершин ламаної, які задають у такому порядку: (XI, Yl, Х2, Y2, ХЗ, „Y3, ... Xn, Yn). Якщо XI = Хп і Yl = Yn, то на екран виводиться багатокутник з кількістю (PixNumb-1) вершин. 4.1.8. Виведення дуги, кола, еліпса SArc (X, Y, AnglS, AnglE, R); - виводиться дуга кола з центром у точці з координатами (X, Y) (тип Integer) і радіусом R (тип Word). Початковий AnglS і кінцевий AngleE Дуга X, Y
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 251 AnglE кути (тип Word) задають у градусах. Дугу проводять проти годинникової стрілки. Коло s Circle (X, Y, R) ; ВИВОДИТЬСЯ коло радіусом R (тип Word) з центром у точці з координатами (X, Y) (тип Integer). У Ellipse (X, Y, Еліпс Angles,AngleE, R_X , R_Y); - виводиться еліптична дуга з центром у точці з координатами (X, Y) (тип Integer) І ПІВОСЯМИ R__X І R__Y (тип Word). Початковий Angles і кінцевий AngleE кути (тип Word) задаються в градусах. Дуга малюється проти годинникової стрілки. Для малювання повного еліпса задаємо: Angles :=0 ; AngleE:=360;. 'S GetArcCoords (Coords) ; - визначення параметрів останнього звертання до процедури Arc чи Ellipse. У програмі повинен бути присутнім опис: Var Coords : ArcCoordsType; ArcCoordsType - тип даних, визначений у модулі Graph як запис (Record), що складається із шести полів, які після звертання до функції GetArcCoords міститимуть таку інформацію: • Coords. х, Coords. Y - координати центра дуги; • Coords. Xstart, Coords. Ystart - координати початкової точки дуги; • Coords.Xend, Coords.Yend - координати кінцевої точки дуги. 4.1.9. Вибір типу лінії для малювання S SetLineStyle (LineType, UserStyle, Width); - встановлення типу ліній рисунка. Тип усіх змінних - Word (табл. 4.3).
252 4.1. Графічне середовище BP Таблиця 4.3 Можливі значення змінної LineType Вид лінії на екрані 0 SolidLn Суцільна 1 DottedLn Крапкова 2 CenterLn Штрих-пунктирна 3 DashedLn Пунктирна 4 UserBitLn Обумовлена користувачем Якщо значення LineType перебуває у межах 0.. З, то значеннями змінної Users tyle ігнорують. Якщо ж LineType = 4, то проводять лінію за зразком, який закодовано у User style. Тут подано спосіб зображення лінії на відрізку довжиною у 16 пікселів: • змінній Users tyle присвоюється число, двійкове представлення якого має наступний зміст: 1 відповідає крапці на екрані, а 0 відповідає пробілу; • width - ширина лінії, яку задають або цифрою, або назвою відповідної константи згідно з табл. 4.4. Таблиця 4.4 Значення змінної Width Ширина лінії 1 SolidLn Звичайна (1 піксел) 3 DottedLn Жирна (3 піксели) 4.1.10. Вибір структури заповнювача ділянок екрана S setttlistyle (FillStyle, Color); - структура заповнювача. Тип усіх змінних Word. Змінна FillStyle забезпечує вибір одного з дванадцяти можливих шаблонів штрихування замкнених фігур на графічному екрані. Її значення задають або цифрою, або назвою шаблону відповідно до табл. 4.5. Зображення можливих шаблонів подано на рис 4.1. Таблиця 4.5 1 Значення змінної FillStyle | Тип шаблону 0 EmptyFill Колір тла 1 SolidFill Суцільне заливання 2 LineFill Г оризонтальні лінії 3 L tSlashFi.il Похилі (/) лінії 4 SlashFill Похилі (/) жирні лінії 5 BkSlashFill Похилі (\) жирні лінії 6 L tBkSlashFill Похилі (\) лінії 7 HatchFill Тонкі ґрати
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 253 Значення змінної FillStyle Тип шаблону 8 XbatchFill Товсті ґрати 9 In terleaveFill Часті ґрати 10 WideDotFill Часті крапки 11 CloseDotFill Рідкі крапки 12 UserFill Обраний користувачем шаблон Рис. 4.1. Шаблони заливання Штрихування наносять кольором Color. Тло екрана просвічується через узор штрихування. Зі зміною кольору тла штрихування з’являється на новому тлі. 4.1.11. Програма показу шаблонів зафарбовування Демонстраційна програма показу стилів зафарбовування замкнутих фігур, яка виводить на графічний екран 12 еліпсів, заповнених різними шаблонами. Номери шаблонів виведено праворуч від еліпсів. Результат роботи програми див. вище (рис. 4.1). Program XIO_FillDemo; Uaes Crt, Graph; Var Drv, Drm, i, j, k, L, m : Integer; Txt : String [ 5 ]; BEGIN Drv := Detect; InitGraph (Drv , Drm , 'C:\BP\Bgi'); SetColor ( Green ); SetBkColor ( White ); K := 120; M := 1; For i:=l to 3 do
254 4.1. Графічне середовище BP Begin L := 100; For J:=l to 4 do Begin Ellipse (L, k, 0, 360, 35, 60) ; SetFillStyle (m, Red); FloodFill (L, k, Green); Str (m, Txt); SetTextStyle (5, 0, 4); OutTextXY (L+33, K, Txt) ; L := L + 120; m := m + 1 End; K := K + 125 End; Repeat Until KeyPressed END. S SetFillPattem (Filling, Color) ; - установлення стилю і кольору заповнення на вибір користувача: • Для зафарбовування ділянок екрана користувачу необхідно обрати заповнення кольору Color (тип - Word) і структури, визначеної в масиві Filling. Цей масив необхідно описати так: Var Filling : Array [1..8] of Byte;. За допомогою цього масиву орнамент заповнення описують для ділянки екрана (8*8) крапок, а потім використовують для покриття всієї необхідної площі (за принципом паркету). У масиві Filling кожен «елемент задає структуру одного рядка в поле орнаменту. Вибір значення для кожного елемента масиву виробляється аналогічно до вибору значення для зразка (UserStyle) у процедурі SetLineStyle (див. параграф 4.1.9). 4.1/12. Заливання замкнутої області 'S Floodrill (X, Y, Border Color); - заповнення замкнутої області. Однозв’язна область, обмежена одноколірним контуром кольору BorderColor (контур без розривів) заливається заповнювачем, тип якого встановлений у процедурі SetFillStyle. Необхідно, щоб точка з координатами (X, Y) належала області, що заливається, окрім її межі. Усі змінні типу Word.
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 255 4.1.13. Виведення на екран заповнених фігур S Bar (XI, Y1, Х2, Г2; зафарбований прямокутник (без окантовки). Тип і призначення параметрів ті ж, що й у процедурі Rectangle. / FillEllipse (СХ, CY, Axe, Axe) заповнений ЄЛІПС. Тип і призначення параметрів ті ж, що й у процедурі Ellipse, проте (на відміну від процедури Ellipse) будується не дуга, а повний зафарбований еліпс. S PieSlice (X, Y, AngleS, AngleE, R) зафарбований сектор. Тип і призначення параметрів ті ж, що й у процедурі Arc. На відміну від процедури Arc, тут будується не дуга, а зафарбований сектор. S Sector (X, Y, Angle, Angle, Axe, Axe); - заповнений еліптичний сектор. Тип і призначення параметрів ті ж, що й у процедурі Ellipse. Відмінність від процедури Ellipse: будується не еліптична дуга, а зафарбований еліптичний сектор. S FilUPoly (PixNumb, VertexCords) ; - на екран виводиться зафарбований багатокутник, що має PixNumb вершин (тип - Word). Координати вершин задаються в масиві VertexCords так само, як і для процедури DrawPoly. Тип заповнювача необхідно визначити заздалегідь у процедурі Se tFillStyle. 4.1.14. Виведення тексту на екран S SetTextStyle (TextStyle, Direction, Hight); - встановлення типу шрифту. Усі змінні типу Word. Значення параметрів процедури SetTextStyle подано у табл. 4.6. Таблиця 4.6 І Значення змінної TextStyle Тип шрифту Значення змінної Direction Значення змінної Hight 0 Binary 0 - зліва праворуч; 1 - знизу вгору Розмір символів 1 Triplex 2 Small 3 sanserif 4 Gothic
256 4.1. Графічне середовище ВР Увага! Усі стандартні графічні шрифти ВР з номерами 1.. 4 не містять кирилиці. Кирилиця міститься тільки в шрифті Binary. Її також можна виводити на графічний екран за допомогою операторів Write і Writeln. У мережі Internet є сайти, звідки можна завантажити файли кирилізованих графічних шрифтів для системи ВР і замінити ними стандартні файли *.chr. S SetUserCbarSize (Multi, Divl, Mult2, Div2); установка власного розміру шрифту програмістом. Ця процедура не діє на шрифт типу Binary. Усі параметри мають тип Word. Масштаб по осі Ох дорівнює Multl/Divl. Масштаб по осі Оу дорівнює Mult2/Div2. Таблиця 4.7 Еквівалентність розмірів шрифтів № шрифту і його тип Розмір шрифту в SetTextStyle Розмір в SetUserCharSize 1 Triplex 1 6/10 2 Small 4 10 / 10 3 SanSerlf 1 6/10 4 Gothic 2 6 /10 Розмір 10 у процедурі SetTextstyle відповідає розміру 40/10 у Процедурі SetUserCbarSize. 'S SetText Justify (Horizont, Vertic); - вирівнювання тексту. Обидві змінні належать до типу Word. Значення параметрів процедури подано у табл. 4.8. Таблиця 4.8 Горизонтальне вирівнювання тексту Вертикальне вирівнювання тексту Значення змінної Horizont Спосіб вирівнювання тексту Значення змінної Vertic Спосіб вирівнювання тексту 0 По лівому краю 0 По нижньому краю 1 Центрування 1 Центрування 2 По правому краю 2 По верхньому краю Вирівнювання тексту здійснюється відповідно координат (X, Y) у процедурі OatTextxr, або щодо поточної позиції графічного курсора у процедурі OutText. S OntText (Txt); - виведення тексту в поточне місцезнаходження графічного курсора. Txt - це константа або змінна символьного (Char) чи рядкового (String) типу, що містить текстову інформацію, яку
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 257 необхідно вивести на графічний екран. Текст виводиться на екран відповідно до обраних атрибутів. Вирівнювання тексту виконується щодо поточної позиції графічного курсора. S OutTextXY (X, Y, tfxt) ; - виведення тексту в певну позицію на екрані, яка визначається координатами (X, Y), що мають тип Integer. Ця позиція є точкою, щодо якої відбувається вирівнювання тексту. 4.1.15. Програма виведення діаграми та гістограми Program XIOJDiagranuna; Uses Crt, Graph; Var Drv, Drm : Integer; BEGIN Drv := Detect; InitGrapb (Drv,Drm, 'C: \BP\BGI1) ; SetBkColor(White); Setcolor(Green); SetFlllStyle (10, Green); Pleslice (100, 100, 0, 60, 50J; Bar3d (200, 400, 300, 340, 50, TopOn); OutTextXy (145, 70, '25%'); SetFlllStyle (A, Red); PieSlice (100, 100, 60, 240, 50); Bar3d (200, 340, 300, 160, 50, TopOn); SetFlllStyle (7, Magenta) ; PieSlice (100, 100, 240, 360, 50); Bar3d(200, 160, 300, 40, 50, TopOn); Repeat Until Keypressed END 9 7-451 Рис. 4.2. Результат робота програми
258 4.1. Графічне середовище ВР 4.1.16. Програма, яка виводить шахову дошку Program Xio_Desk; Uses Crt,Graph; Var Drv, Drm, i, j, x, у : Integer; t, g : Char; BEGIN Drv := Detect; InitGraph(Drv, Drm, 'C:\BP\Bgi'); SetFillStyle(1, White); Bar(Of 0, 400, 400); SetFillStyle(1, Вrown); У := 0; For j := 1 to 4 do Begin x:=0; For і := 1 to 4 do Begin Bar(x, y, x + 50, у + 50); Bar(x + 50, у + 50,x + 100, y+100); x := x + 100 End; у := у + 100 End; x := 25; у := 25; SetColor (Whi t e); SetFillStyle(1, 15); For i:=l to 4 do Begin Circle(x, y, 17); FloodFill{x, y, 15); Circle(x f 50, У + 50, 17); FloodFill{x + 50, у + 50, 15); Circle(xf у + 100, 17); FloodFill{xf у + 100, 15); x := x + 100 End; x := 75; у := 275; SetColor(Green); SetFillStyle(1, Green); For і := 1 to 4 do Begin Circle(x, y, 17); FloodFill{x, y, Green); Circle{x - 50, у + 50, 17); FloodFill{x - 50, у + 50, Green); Circle{xf у + 100, 17); FloodFill{xf у + 100,, Green); x := x + 100 End; Repeat Until KeyPressed END.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 259 Рис. 4.3. Результат роботи програми 4.2. Побудова графіків функцій Графічне представлення результатів фізичних досліджень використовують досить часто внаслідок його наглядності. Розглянемо розв’язання цієї задачі як з погляду математики, так і з погляду програмування. 4.2.1. Математичний аспект Побудуємо графік всередині уявного вікна, яке утвориться внаслідок відступу по периметру на L> 20 пікселів від країв екрана (для виводу цифр і тексту). Нехай на екран необхідно вивести Ne експериментальних точок (Ne<640 ) з координатами (Х<?;,Уе,), і = 0..Ne-1. Позначимо: Min X = тіпКеі; Min Y = min Yet; і і МахХ = тахХеі; MaxY = max Yet. І і Для виведення графіка функції /(де), яку задано аналітично на проміжку х є [а/, bl] , матимемо (див. рис. 4.4): МіпХ = al; МахХ = bl; MinY = minf (x) ; MaxY = maxf (*). [al.bl] [al,bl] Побудову графіка виконуємо за такими правилами:
260 4.2. Побудова графіків функцій оскільки діапазон зміни координат графічного екрана УЄА фіксований (X є/г0..639/ У є[0..479]), а експериментальні дані можуть змінюватись у широких межах, то для виведення усіх точок на весь екран (вікно АВСО на рис. 4.4), експериментальні дані потрібно промасштабувати шляхом домноження координат кожної точки на масштабні коефіцієнти Кх і Ку. У цьому випадку коефіцієнт Ку буде від’ємним, щоб компенсувати те, що на екрані вісь Оу спрямована зверху вниз, а не навпаки. Рис. 4.4. Графік на екрані ПК Додаванням певних величин 2х і Іу до промасштабованих експериментальних значень ми переходимо від реальної системи координат (Хе, їе) до екранної (АГ, У). Цей перехід здійснює лінійне відображення: Х = Кх-Хе + & ї=ку їе+гу ‘ (4'21) Позначимо через Мх і Му максимальну, для заданого режиму, кількість пікселів екрана по горизонталі і вертикалі (її отримують з допомогою функцій ЄеіМахХ і ЄеіМахУ). Коефіцієнти перетворення (4.2.1) обчислюються за формулами: Мх-2*Ь уМу-2*Ь Х~ МахХ-МіпХ' У~ Міпї-МахУ' Мх-МіпХ -Ь • (МіпХ +МахХ) _ Му • Махї -Ь • (МшГ +Мах¥) (4.2.2) МіпХ - МахХ ^ Махї -Міпї
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 261 Отож, при побудові графіка у програмі в циклі по і = 0..Ne -1 відбудеться виведення на екран пікселів з координатами: (Xj,Yj) = (Round(Kx • XEj + Zx), Round(Ky • Щ + Zy)). (4.2.3) Осі координат програмуємо “плаваючими”, тобто їхнє положення на екрані не є фіксованим, а залежить від значень, MinY, MaxY. Вісь Ох проводимо че МіпХ, МахХ рез мінімальне за модулем число з проміжку [MinY, MaxY]. Вісь Оу - через мінімальне за модулем число з проміжку [МіпХ, МахХ]. При побудові координатних осей на папері координати точки їхнього перетину (Gx, Gy) обчислюють із таких умов: 0, якщо МіпХ ■МахХ <0; Gx = < МіпХ, якщо МіпХ •МахХ >0 і МіпХ > 0; МахХ, якщо МіпХ •МахХ > 0 і МіпХ < 0. (4.2.4) 0, якщо MinY -MaxY < 0; Gy = • MinY, якщо MinY •MaxY > 0 і MinY > 0; MaxY, якщо MinY •MaxY > 0 і MinY < 0. Проте на екрані координатні осі задаються прямими, кінці яких мають координати: Ox. Xj,Yj= (L,Round(bx))\ X2,Y2=(Mx-L,Round(bx)); (4.2.5) Oy: X„Yj= (Round(ay),L); X2,Y2= (Round(ay),My - L); . Параметри ay, bx (див. рис. 4.2) отримаємо, підставляючи (Gx, Gy) з умов (4.2.4) у перетворення (4.2.1): ay = Kx-Gx + Zx: LKyGy.Zy. <4-2'6) На побудованих осях наносимо масштабні поділки в кількості, наприклад, ю штук; підписуємо кожну з них відповідним числовим значенням, використовуючи процедури Str і OutTextXY. Побудований графік для перегляду затримуємо на екрані оператором: Repeat Until KeyPressed;.
262 4.2. Побудова графіків функцій 4.2.2. Аспект програмування Завдання. 1. Отримати у викладача аналітичний вираз функції для виведення на графік і запрограмувати її як PascaZ-функцію. 2. Написати PascaZ-програму виведення графіка, описуючи, необхідні для його побудови змінні і масиви. Масиви описати, створюючи структуру нестандартного типу, наприклад: Type Vector = Array[0..64 0] of Real;. 3. У виконуваній частині програми: а) запрограмувати введення з клавіатури значень кінців проміжку виведення функції на графік (називаючи їх, відповідно, аі і bt) і числа Ne пар експериментальних значень; б) заповнити, шляхом табулювання заданої функції, масиви значень для виведення на графік (масиви Хе і Ye); в) визначити максимальні і мінімальні значення елементів цих масивів; г) за формулами (4.2.2) обчислити значення коефіцієнтів масштабування; д) враховуючи вирази (4.2.4), (4.2.5) і (4.2.6), накреслити осі координат; е) за виразом (4.2.3) з допомогою циклу побудувати графік - заданої функції. 4. Передбачити виведення на осі координат масштабних поділок і виведення (у текстовому вигляді) відповідних щодо них числових підписів.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 263 4.2.3. Програма побудови графіків функцій Program ХІО_2 GRF; { Якщо прибрати затемнені частини, будуватиметься один графік } Uses Crt, Graph; Type Vector = Array [0..640] of Real; Var XE, YE§f$#£§®£ : Vector; MaxX,MaxY,MinX,MinY,MaxXG,MaxYG,MinXG, MinYG : Real; Kx,Ky,Zx,Zy,Gx,Gy,al,bl,h,Krx,Kry,xx,yy : Real; Ne, Hgr, і, j, KrokX, KrokY, Drv, Drm, L : Integer; Txt : String; Function £ (x : Real) ; Real; Begin f := x * Sin (x) End; Function £1 (x : Real) : Real; Begin End; BEGIN {Початок головної програми} Writeln (’Введіть к-сть точок: Ne Ngr кожного графіка'); Readln ( Ne£;Ngr ); Writeln ( 1 Введіть проміжок al bl (область визначення)'); Readln ( al, bl); {al bl —> межі зміни аргументу} { Табулювання функції f із занесенням результатів у масиви Хе Ye} h:=(bl-al)/(Ne-1); { h -> крок табулювання функції f} ХЕ[0] := al; For і := 0 to Ne - 1 do Begin YE [i] := f (Xe [i]); XE [i + 1] := Xe [i] + h End; { Табулювання функції £1 із занесенням результатів у масиви Xg Yg} h:»(bl-al)/(Ngr-1); {h-> крок табулювання функції £1} Ж fO] al; For і 0 Шф Шдх ~ 1 do Begin YG [і] :« fl (Xg fi) ) ; XG fi + ' :« Kg fi] + h - End; { Перемикання екрана у графічний режим роботи} Drv := Detect; InitGraph (Drv, Drm, ’C:\BP\BGI1); SetBkColor (White); {Колір тла - білий } L := 60; {L -> відступ від країв екрана для підписів }
264 4.2. Побудова графіків функцій { Пошук екстремальних значень аргументу і функції f } 5? МіпХ := Хе [0]; МахХ := Хе [Ne - 1]; fl MinY := Ye [0]; MaxY := Ye [0]; I For i:=l to Ne-1 do J Begin If MaxY < Ye [i] then MaxY := Ye [i] ; f If MinY > Ye [i] then MinY := Ye [i] | End; { Пошук екстремальних значень аргументу і функції £1} | MinYg :» Уд [0]; МахУд Уд [0]; і; For і- :* 1 tó 1х do І» Begin If МахУд < Уд [і] then МахУд :« Уд [і]/ ;■ Х£ МіпУд > Уд [і] then МіпУд.Уд [і] 1 ' Bnd;™ ; If Махуд > MaxY then МахУ :** МахУд; І If Міпуд < МіпУ then МіпУ :» МіпУд/ | { Обчислення коефіцієнтів масштабування } | Кх := (GetMaxX - 2 * L) / (МахХ - МіпХ)/ І Ку := (GetMaxY - 2 * L) / (MinY - MaxY); Zx := (GetMaxX * MinX - L*(МіпХ + MaxX))/(MinX-MaxX); ! Zy := (GetMaxY * MaxY - L*(MinY + MaxY))/(MaxY-MinY); {Побудова осей кроординат} If МіпХ * МахХ <= 0 then Gx := 0; ś If ( МіпХ * MaxX > 0 ) then Gx := МіпХ; і It ( MinX * Max* > 0 ) And ( MinX < 0) then Gx:=MaxX; If MinY * MaxY <= 0 then Gy := 0; | If ( MinY * MaxY > 0 ) And ( MinY > 0) then Gy:=MinY; If ( MinY * MaxY > 0 ) And ( MinY < 0) then Gy:=MaxY; | SetColox.(Red); * SetLineStyle (SolidLn, 2, 3) ; Line (L, Round (Ky * Gy +Zy) , Round (GetMaxX - L) , Round (Ky * Gy + Zy) ) ; Line (Round (Kx * Gx + Zx), L, Round (Kx* Gx + Zx), J Round (GetMaxY - L) ) ; { Обчйслення відстаней між лініями гратки по осях X та Y, відповідно } KrokX := (GetMaxX - 2 * L) Div 10; KrokY := (GetMaxY - 2 * L) Div 10; 1 SetlineStyle (3, 0, 1) ; j SetColor (Magenta) ; {Побудова гратки } For i:=l to 10 do 3 Begin Line (L, L + i*KrokY, GetMaxX - L, L + i*KrokY); Line (L + i*KrokX, L, L + i*KrokX, GetMaxY - L) ; End; xx := Minx; yy := Maxy; {Обчислення кроків зміни значень масштабних підписів по осях X та Y, відповідно }
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 265 Кгх := (МахХ - МіпХ) /10; Kry := (MaxY - MinY) /10; SetTextStyle (2,0,5); SetTextJustify (0, CenterText); { Виведення масштабних підписів } For і := 0 to 10 do Begin Str (xx:7:2, Txt); I OutTextXY (L-32+i*KrokX, GetMaxY-Ь Div 2 - 5,Txt); Str(yy:7:2, Txt); | OutTextXY (L - 60, L + і * KrokY, Txt); xx := xx + KrX; yy := yy - KrY J End; SetColor (Blue); I SetLineStyle (0, 0, 1) ; { Побудова графіка функції f кружечками} For i:=0 to Ne - 1 do J Circle (Round (Kx*Xe[i]+Zx), Round (Ky*Ye[i]+Zy),1); | SetColor {Green)? { Побудова графіка функції fl лініями} ' MoveTo (Round (Kx*Xg[0]+Zx), Hound <Ky*Ygf0}+Zy)); For- i:**0 ' to $gr ^ LineTo (Round (Kx*Xg[i]+Zx), Round (Ky*Yg[i]+Zy)); SetColor ( Red ); SetLineStyle (0,0,1); RectAngle (L, L, GetMaxX - L, GetMaxY - L) ; Repeat Until KeyPressed & END. .-30.00 -24.00 -18.00 -12.00 -6.00 -0.00 6.00 12.00 18.00 24.00 30.00 Рис. 4.5. Результат робота програми у випадку однієї функції
266 4.3. Програмування рухомих зображень 4.3. Програмування рухомих зображень 4.3.1. Вказівники і динамічна пам'ять Оперативна пам’ять (ОП) ПК, який працює у реальному режимі (базовому режимі роботи MS DOS) становить 1Мб. З них 640Кб використовує ядро ОС і прикладна програма (у нашому випадку - PascaZ-програма). При цьому пам’ять умовно розділяється на неперервні ділянки по 65 536 байт (64Кб), які називають сегментами. Код програми і дані, які вона обробляє, займають один або декілька сегментів; 200 - 300Кб пам’яті є вільними, і їх можна використати як проміжний буфер для тимчасового зберігання даних. Цю вільну область називають динамічною пам’яттю. Схематично розподіл перших 640Кб ОП можна зобразити так: Системна Код Стек Сегмент Динамічна область Системна область програми (16Кб) даних (64К6) пам’яті (Неер) область Borland Pascal дає змогу прикладній програмі використовувати частину або всю динамічну пам’ять завдяки механізмові вказівників. Вказівник - це змінна, яка містить не число, а адресу деякого байта оперативної пам’яті. Змінна-вказівник завжди займає у пам’яті 4 байти. З допомогою вказівників адресують початки будь- яких фрагментів динамічної області ОП. Вказівники бувають типізовані і нетипізовані. Типізований вказівник описують так: Var Р1 : Л Integer; або Р2 : ЛИеа1;. Перший рядок означає, що Р1 міститиме під час роботи програми адресу цілого двобайтового числа. Інший вказівник Р2 міститиме адресу шестибайтового дійсного числа. Нетипізований вказівник із жодним конкретним типом даних не пов’язаний. Для його опису у мові Pascal є окремий тип даних - Pointer. Описують нетипізовані вказівники так: Var рз : Pointer;. Якщо у програмі необхідно записати чи зчитати дані з використанням нетипізованих вказівників, то адресу, яку подає вказівник РЗ, позначають так: РЗЛ. Нетипізовані вказівники зручно використовувати для програмування рухомих зображень.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 267 4.3.2. Алгоритм переміщення зображення графічним екраном Щоб отримати рух зображення графічним екраном, спочатку програмують такі кроки: • Перемикають екран у графічний режим роботи процедурою InitGraph. • Створюють рисунок, використовуючи підпрограми модуля Graph.tpu. • Охоплюють рисунок уявним прямокутником, визначаючи щодо цього екранні координати його лівого верхнього (XI, Y1) та правого нижнього (Х2, Y2) кутів. • Функцією ImageSize (XI, Yl, Х2, Y2) отримують число байтів, необхідних для запам’ятовування прямокутника із зображенням у динамічній пам’яті і присвоюють це число змінній size типу Integer, наприклад: Size := ImageSize (XI, Yl, Х2, Y2);. • Процедурою GetMem (РЗ, Size); резервують у динамічній пам’яті необхідний масив байтів для зберігання зображення (число байтів міститься у змінній Size; адреса початку масиву запишеться у вказівник РЗ). • Процедурою Get Image (XI, Yl, Х2, Y2, Buffer); записують прямокутну ділянку екрана з координатами (XI, Yl, Х2, Y2) в область памяті, задану змінною Buffer. При записі у динамічну пам’ять змінною Buffer слугує адреса, задана вказівником РЗА. Ілюзія руху виникатиме, якщо почергово читати зображення з динамічної області пам’яті, записувати його в певне місце графічного екрана, стирати його після певного часу затримання і, змінюючи координати місця знаходження зображення в напрямі руху, знову і знову повторювати: записування на екран, затримання, стирання зображення. Зчитування графічного фрагмента з динамічної пам’яті здійснюють процедурою:
268 4.3. Програмування рухомих зображень PutTmage (X, Y, Buffer, Mode) де х, Y - координати лівого верхнього кута прямокутника, у який буде поміщено зображення після його зчитування з динамічної пам’яті. Роль змінної Buffer виконує адреса РЗЛ. Параметр Mode задає спосіб взаємодії пікселів ділянки екрана, куди відбувається зчитування зображення з пікселами самого зображення. Він набуватиме одного з п’яти значень, поданих у табл. 4.9: Таблиця 4.9 Параметр Mode процедури Put Image Назва константа Її значення Що відбувається ? Normal Put 0 Існуюче зображення заміниться копією відповідного фрагмента динамічної пам’яті XorPut 1 Заміна відбудеться за правилами роботи логічної функції виключаюче АБО OrPut 2 Заміна відбудеться за правилами роботи функції АБО AndPut 3 Заміна відбудеться за правилами роботи функції І NotPut 4 Відбудеться інверсія зображення Стирання зображення з екрана перед його переміщенням можна здійснити одним із двох способів: 1)' Окрім прямокутника з рисунком записати у динамічну пам’ять прямокутник такого ж розміру, що містить фон (порожню ділянку екрана). Після затримання показу зображення зчитати у місце його знаходження прямокутник із фоном і стерти тим самим зображення. 2) Порожній прямокутник не запам’ятовувати, а оточити наш рисунок більшим прямокутником, сторони якого віддалені від країв рисунка на ь пікселів. Якщо крок зміни координат зображення вибирати меншим за ь, то нова копія зображення затиратиме попередню.
4. ВІЗУАШЗАЦМ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 269 4.3.3. Програма, що виконує рух кульки екраном Program Jadro; Uses Crt, Graph; Var Drv, Drm, і: Integer; P : Pointer; {Змінна - вказівник} Size : Word; {Змінна, яка містить розмір зображення} BEGIN Drv := Detect; InitGraph(Drv,Drm,1C:\BP\BGI'); {Перемикає екран у графічний режим роботи} SetColor (Magenta); {Колір зображення - бузковий} SetBkColor (Blue); {Колір фону - синій} For і := 1 to 10 do Circle (20, ЗО, і); {Рисує кульку радіусом 10 пікселів} Size := ImageSize (9, 19, 31, 41); {Визначає "об'єм" у байтах прямокутника з рисунком } GetMsm (Р, Size); {Резервує у динамічній пам'яті потрібну кількість байт} Getlmage (9, 19, 31, 41, Рл); {Записує у динамічну пам'ять прямокутник з рисунком} Repeat Until Keypressed; {Затримує показ зображення на екрані} ClearDevice; {Очищає графічний екран} For і := 1 to 600 do {Цикл для зміни координат кульки, щоб вона рухалась праворуч} Begin Putimage (10 + і, 10, РА, NormalPut) ; {Записує зображення з динамічної пам'яті на екран} Delay (35) {Затримує показ зображення} End; For і := 600 downto 1 do {Цикл для зміни координат кульки, щоб вона рухалась ліворуч} Begin Putimage (10 + і, 10, Рл, NormalPut); {Записує зображення з динамічної пам'яті на екран} Delay (35) {Затримує показ зображення } End; Repeat Until Keypressed {Затримує показ зображення} END. * Ця програма виконуватиме рух кульки по горизонталі зліва направо, і навпаки. Якщо слово Repeat розташоване у третьому знизу операторі, перенести і поставити після оператора
270 4.3. Програмування рухомих зображень ClearDevice;, то виконуватиметься неперервний рух кульки, аж до натискання будь-якої клавіші. Якщо в обох операторах: Putlmage (10+і, 10, РА, NormalPut); другий параметр 10 замінити на 10+і, а максимальну кількість повторень обох циклів For зменшити до 450, то виконуватиметься коливання кульки по діагоналі екрана. Завдання для самостійної роботи: • Запрограмувати неперервний рух кульки по контуру прямокутника вздовж кожної зі сторін екрана. • Запрограмувати неперервний рух кульки вздовж прямокутної спіралі. • Запрограмувати неперервний рух кульки синусоїдою. 4.4. Керування рухом зображення графічним екраном 4.4.1. Алгоритм керування рухом зображення Доцільно в ролі керуючих клавіш обрати цифрову частину клавіатури, яку попередньо вмикають клавішею NumLock . \ \ / □шш -ЕНЕЬ ИЕЗШ / і \ Рис. 4.6. Пов’язування клавіш з напрямом переміщення Обираємо кожну із цифрових клавіш відповідальною за переміщення зображення в одному напрямі (рис. 4.6). Клавіша з цифрою 5 передбачає повертання зображення у центр екрана. Механізм керування є таким: для читання коду натиснутої клавіші використовуємо стандартну функцію Кеа<2Кеу, яка входить у модуль СгЬ. Для цього використовуємо оператор: If KeyPressed then С := ReadKey;,
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 271 який (у випадку, коли якась клавіша є натиснутою) помістить у символьну змінну с код цієї клавіші. Послідовність роботи програми:. • Перемикаємо екран у графічний режим роботи. • Визначаємо уявний квадрат графічного екрана, у який згодом помістимо наш рисунок; і обчислюємо його розмір у байтах. • Резервуємо у динамічній пам’яті область об’ємом, що є достатнім для запису туди квадрата із зображенням, яким рухатимемо, використовуючи механізм нетипізованих вказівників. • Графічними процедурами створюємо всередині вибраного нами уявного квадрата рисунок, наприклад, кольоровий диск. • Записуємо квадрат із зображенням у динамічну пам’ять. • Для програмування обраного напряму переміщення використовуємо оператор Case, у якому змінна С відіграє роль селектора. Залежно від натиснутої цифри, збільшуємо чи зменшуємо одну чи обидві координати і згодом затираємо пробілом код обраної клавіші, що містився у змінній с. • Чотири оператори if, які працюють після оператора Case, забезпечують зупинку зображення при досягненні ним одного з країв екрана. 4.4.2. Програма керування рухом зображення Program XIO_Control; Uses Crt, Graph; Var Drv, Drm, і, X, Y, Size, Mx, My : Integer; Pk : Pointer; C : Char; BEGIN Drv := Detect; InitGraph ( Drv, Drm, 'C:\BP\BGI'); Mx := GetMaxX; My := GetMaxY; X := Mx Div 2; Y := My Div 2; Size := ImageSize ( 0, 0, 20, 20); GetMem ( Pk, Size); SetColor ( Green ); For і := 1 to 5 do Circle (10, 10, i) ;
272 4.4. Керування рухом зображення графічним екраном GetTnage (0, 0,20, 20, PkA) / ClearDevice; Repeat Putlmage (X, Y, PkA, 0); If KeyPressed then C := ReadKey; Case C of 1' : Begin X = X - 5; Y = Y + 5; C := ' ' End; 2' : Begin Y = Y + 5; C = » ' End; 3' : Begin X = X + 5; Y = Y + 5; C := ’ ' End; 4’ : Begin X = X 5; C = » ' End.; 6’ : Begin X = X + 5; C = i ' End; 7' : Begin X = X - 5; Y = Y - 5; C := ' ' End; 8і : Begin Y = Y 5; C = i 1 End; 9' : Begin X = X + 5; Y = Y - 5; C := ' ' End; End; If X <= 1 then X := X + 5; If X >= Mx - 21 then X := X - 5; If Y <= 1 then Y := у + 5; If Y >= My - 21 then Y := Y - 5; Delay (10); Until(C = ’q') or ( C = ' q’) END. 4.5. Записи (Record) Як у програмуванні, так і в житті нерідко виникає необхідність використання деяких елементів як складової частини іншої, дещо крупнішої логічної одиниці. Наприклад, природно згрупувати інформацію про номер будинку, вулицю і місто в одне ціле і назвати це адресою, а об’єднану інформацію про день, місяць і рік народження - датою. У мові Pascal для представлення сукупності різнорідних даних слугує комбінований тип Record (запис). Синонімом цього терміна може бути термін структура. Узагальненням цього поняття є база даних. За своєю природою запис подібний до масиву, оскільки обидві ці структури сформовані із набору окремих компонент. Водночас, якщо компоненти масиву обов’язково повинні бути одного типу, записи можуть містити компоненти різних типів. Кожну компоненту запису називають полем. Приклад опису змінної, що має структуру типу запис:
4. ВІЗУАШЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 273 Var Address ; Record HouseNumber : Integer; StreetName : String [20]; CityName : String [20]; PeopleName : String; End; Зазначимо, що поля StreetName і CityName мають однаковий тип: String [20]. Це дає змогу скоротити опис запису Address з полями однакового типу: Var Address : Record HouseNumber : Integer; StreetName, CityName: String [20]; PeopleName : String; End; У змінній Address, яка має тип Record, поле з іменем HouseNumber є змінною типу Integer, поле StreetName є двадцятисимвольним рядком і т.д. Щоб звернутися до будь-якого із полів запису, необхідно зазначити ім’я змінної та ім’я поля, розділяючи ці два ідентифікатори крапкою. Наприклад, оператор присвоєння полю HouseNumber числового значення 5 виглядатиме так: Address.HouseNumber := 5;. Аналогічно можна присвоїти значення іншим полям запису Address: Address.StreetName := 'Драгоманова1; Address.CityName := ’Львів’; Address.PeopleName := 'Кованько Степан';. Кожне поле запису з іменем Address можна розглядати як звичайну змінну, яку можна надрукувати чи використати в розрахунках. Водночас запис можна використовувати як єдине ціле. У цьому випадку вводять власний тип, що містить структуру типу Record, описуючи його так: Type Date = Record Day : 1..31; Month : (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); Year : Integer; End; Var Birth, My Birth : Date;
274 4.5. Записи У нашому прикладі змінні Birth і MyBirth мають тип запису на ім’я Date. Окрім дій над окремими полями записів Birth і MyBirth можна виконувати операції над усім записом. Наприклад, наступний оператор зкопіює значення полів запису MyBirth у відповідні поля запису Birth: Birth := MyBirth;. Це присвоєння є еквівалентним такій послідовності операторів: Birth.Day := MyBirth.Day; Birth.Month := MyBirth.Month; Birth.Year := MyBirth.Year;. До змінних одного типу можна застосовувати перевірку виконання відношення рівності чи нерівності ("=", "О"). Наприклад, після виконання наведених вище присвоєнь наступний логічний вираз матиме значення True: Birth = MyBirth;. Оскільки на тип компонент масиву не накладено обмежень, то можна використовувати масиви, компонентами яких є записи. Наприклад, є граматично вірним опис такого масиву: Var Birthdays : Array [1..Persons] of Date;. Щоб звернутися до* деякого поля певного масиву записів, необхідно написати ім’я масиву, індекс запису (елементу масиву), який нас цікавить, і через крапку - ім’я необхідного поля. Наприклад, наступний оператор виводить на екран вміст поля Year запису Birthdays [3]: Write (Birthdays[3].Year); Примітка. Поля запису, відповідно, теж можуть бути масивами, множинами, записами. 4.5.1. Оператор приєднання With Дотримання усіх правил переліку індексів і імен полів при використанні в операторах полів структури типу Record є досить важким заняттям, що часто спричинює до помилок. У програмах, які містять чималу кількість звернень до полів одного і того ж запису, така ситуація спричинює одноманітне повторення кожного разу імені відповідного запису. Щоб полегшити виконання багатократних посилань для описаних структур, вводять оператор
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 275 With (в перекладі з англійського - прийменник “з”). Його називають оператором приєднання. Загальна форма запису: With <ім' я змінної типу Record> do Begin <оператор> End; У межах складного оператора, утвореного наведеною вище структурою With, до кожного поля змінної типу Record можна звертатися просто за його іменем. Наприклад, фрагмент програми: Address.StreetName := 'Драгоманова'; Address.CityName := 'Львів'; Address.PeopleName := 'Кованько Степан'; з допомогою оператора приєднання можна записати так: With Address do Begin StreetName := 'Драгоманова'; CityName := 'Львів'; PeopleName := 'Кованько Степан'; End; . У рамках складного оператора, розташованого за оператором With, кожне звернення до імені поля автоматично зв’язується із записом, якому це поле належить. Оператори With можуть бути вкладеними. Наведені нижче три оператори еквівалентні один одному: • Payroll[і].Residence.HouseNumber := 50; • With Payroll[і].Residence do HouseNumber := 50; • With Payroll[i] do With Residence do HouseNumber := 50;. Проте неприпустимим є використання вкладених операторів With, у яких зазначено поля одного типу, оскільки виникає неоднозначність конструкції. Внаслідок цього таке використання вкладених операторів With є невірним: With Payroll[5] do With Payroll[17] do PayScale :='A';.
276 4.5. Записи Необхідно вкрай уважно підходити до застосування вкладених операторів With, застосування яких може спричинити не тільки до помилок, але й до втрати наочності структури програми. Хоча оператор With є стандартним засобом скорочення, інколи його корисність буває сумнівною. Кінцевою метою кожного професійного програміста є написання не тільки короткої, але й зрозумілої програми. Приклад. У масиві зберігаються дані про студентів: факультет, прізвище, курс. Вивести на текстовий екран список студентів, які вчаться на старших курсах. Program Students; Uses Crt; Type Student = Record Fakultet : String [12] ; Prizv : String [15] ; Kurs : Integer; End; Var i, j, N, a : Integer; Masyv : Array [1..500] of Student; Procedure Poshuk; Begin For i:=l to n do If Masyv [i].Kurs = 3 then With Masyv [i] do Writeln (Fakultet:12,' f,Prizv:15,1 *,Kurs) End; j BEGIN ClrScr; Write ('Введіть кількість студентів :'); Readln (N); For i:=l to N do Begin Writeln('Введіть через пропуск факультет і прізвище студента '); With Masyv [і] do Begin Readln (Fakultet, Prizv); Write ('Введіть номер курсу ->'); Read (Kurs) • End End; Writeln (' Список студентів третього курсу’); /і Writeln('Факультет Прізвище Курс'); Writeln (' '); Poshuk; Repeat Until KeyPressed End.
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 277 4.5.2. Записи з варіантами Записи, розглянуті вище, називають записами з фіксованими частинами. У різних ситуаціях вони мають строго фіксовану структуру. Відповідно, записи з варіантами в різних ситуаціях можуть мати різну структуру. Нехай ми використовуємо програму для введення списку бібліографічних посилань. Якщо відомо, що всі входи в цьому списку - посилання на книги, то можна використовувати такий опис: Const Kilk = 1000; Type Entry = Record Autor, Title, Publisher, City : String; Year : 1..2006; End; Var List : Array [1. .Kilk] of Entry;. Що відбуватиметься, якщо деякі з входів не є посиланнями на книги, а містять посилання на журнальні статті. Якщо обмежуватися тільки записами з фіксованими частинами, то необхідно описати різні масиви для кожного виду записів. Використовування записів з варіантами дає змогу утворити структуру, кожен вхід якої відповідає змісту запису. Опишемо новий тип, в якому перелічено різні входи: Type Entry туре = (Book, Magazine);. Тепер можна привести відкоректований опис Entry: Type Entry = Record Autor, Title : String; Year : 1..2000; Case EntryType Book : (Publisher, City : String) ; Magazine: (MagName: String; Volume, Issue: Integer) End;. Цей опис ділиться на дві частини: фіксовану і варіантну. Поля Autor, Title, Year належать до фіксованої частини. Частина опису Entry, що залишилася, утворює варіантну частину, структура якої може змінюватися у межах двох альтернативних визначень.
278 4.5. Записи Перший рядок варіантної частини представляє оператор Case, у якому роль селектора відіграє ідентифікатор типу. Значення EntryType використовують як імена двох альтернатив визначення запису. Коли ця компонента має значення Book, можна звертатися до наступних полів: Autor, Title, Year, Publisher, City. Якщо ж вона набуває значення Magazine, то можна звертатися до таких полів: Autor, Title, Year, MagName, Volume, Issue. У такій ситуації виникає законне питання: як програма може берегти інформацію щодо поточного стану кожного запису? Іншими словами, як можна довідатись, що List [3] містить посилання на книгу, a List [ 4 ] - посилання на журнал? Природне вирішення цієї проблеми полягає у додаванні в кожному записі нового поля, названого полем тега. Мова Pascal дає змогу завдяки поєднанню задати опис поля тега у скороченій формі: Type Entry = Record Autor, Title : String; Year : 1..2000; Case TAG : EntryType of Book : (Publisher, City : String) ; Magazine : (»MagName : String Volume, Issue : Integer) End; . Поле, назване tag, є змінною типу EntryType. Коли запис містить посилання на книгу, полю tag необхідно присвоїти значення Book. Коли запис містить посилання на журнал, tag необхідно присвоїти значення Magazine. Наприклад, така послідовність операторів у RefList [12] містить посйлання на книгу: RefList[12].TAG ;= Book; RefList[12].Autor := 'Thomas Hobbes'; RefList[12].Title := 'Leviathan'; RefList[12].Year := 1651; RefList[12].Publisher := ’Andrew Crooke'; RefList[12].City := 'London';.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 279 З метою визначення стану запису з варіантами достатньо перевірити значення поля тега. Тоді процедура, що виводить на екран переданий їй запис, буде такою: Procedure PrintRef (Citation : Entry); Begin Writeln (Citation.Autor); Writeln (Citation.Title); Writeln (Citation.Year); If Citation.TAG = Book then Writeln (Citation.Publisher,, Citation.City) else Begin Writeln (Citation.MagName); Writeln (Citation.Volume1-',Citation.Issue) End End; Варіантна частина може містити довільну кількість альтернатив. Хоча тут, здебільшого, застосовують перераховувальні типи, оскільки вони значно зрозуміліші, проте іменами альтернатив запису з варіантами можуть слугувати ідентифікатори будь-якого порядкового типу. Очевидно, що один ідентифікатор поля не можна двічі використовувати під час описування запису, навіть якщо його застосовують у визначенні різних альтернатив запису з варіантами. Якщо ж цю умову не виконано, то звернення до такого ідентифікатора спричинить до непередбачуваного результату. Примітка. Опис запису з варіантами може мати єдиний закриваючий оператор End. Оскільки будь-який запис може мати лише одну варіантну частину, то End, який є індикатором завершення опису запису, слугує для позначення завершення і її варіантної частини. 4.5.3. Використання записів у графіці Під час виведення на графічний екран замкнутих фігур, заповнених певним кольоровим шаблоном, окрім процедури FloodFill зручно використовувати процедуру FilLPoly. вона дає змогу заповнити заданим шаблоном замкнутий контур, побудований із відрізків ламаної лінії. Виклик процедури є такий: FillPoly (< N >, < ім'я масиву >) ; ,
280 4.5. Записи де: • N - кількість точок зламу лінії; • імя масиву декартових координат цих точок, компонентами якого є пари координат стандартного типу Роіп'ЬТуре, що має структуру типу запис: РоіпЬТуре = Кесогсі X, У : ІпЬедег Епф Приклад: Запрограмувати рух “ракети” графічним екраном зліва направо. Координати точок зламу лінії, яка утворює “ракету”, проілюстровано на рис. 4.7. Заносимо ці коор- оо,зс динати у масив ти, який описано як типізовану константу. Кількість пар координат точок нашого рисунка дорівнює 11. Рис. 4.7. Координата точок зламу контура ‘‘ракета” % Нижче наведено програму, яка виводить на графічний екран “ракету”, залиту синім суцільним шаблоном, а потім переміщує її вздовж екрана зліва направо. Завдання для самостійної роботи Запрограмувати аналогічним способом “ракету”, яка піднімається знизу вгору!
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 281 4.5.4. Програма. Рух "ракети" Зліва направо Program XIO_Raketa; Uses Graph; Const Tr: Array [1..11] of PointType = ( (X: 10 / Y:10), (X:30/ Y:10), (X:40; Y:20), (X:70; y:20), (X:100;Y:30), (X:70; Y:40), (X;40; Y:40), (X:30; Y:50), (X:10; y:50), (X:20; Y:40), (X:20; Y:20)); Var Drv, Drm, I : Integer; P : Pointer; Size : Integer; BEGIN Drv := Detect; InitGraph (Drv, Drm, ' C: \BP\BGI') ; Size := ImageSize (9, 9, 101, 51); GetMem (P, Size); SetColor (Red); SetFillStyle (1, Blue); FillPoly (11, Tr); {Заповнюємо замкнуту фігуру, з 11 точок зламу, шаблоном) SetColor (Yellow); OuttextXY (30, 25, 1Salut1); Line (12, 28, 18, 28); Line( 12, 32, 18, 32); Getlmage (9, 10, 101, 51, pA); Readln; ClearDevice; For i:= 0 to 500 do Putlmage(10+i, 10, PA, NormalPut);- {Переміщення ракети зліва направо) Readln END.
282 4.5. Записи 4.5.5. Використання записів при виведенні ДУГ Задача: Запрограмувати виведення на графічний екран Саму графічну фігуру сформуємо із двох дуг і двох ліній, які виходять З ОДНІЄЇ ТОЧКИ б і є дотичними до кожної з дуг у їхніх кінцевих точках (рис. 4.6). Пульсування означає, що розміри фігури періодично збільшуються від деякого початкового значення до кінцевого, і назад. Вхідною інформацією слугують координати (Х,У) геометричного центра фігури і дві величини: • А - відстань від точки (Х,Т) до верхньої точки сполучення дуг; • • а - відстань від точки (Х,ї) до кожного з центрів дуг. Для зміни розмірів фігури масштабуватимемо ці обидві величини шляхом домноження: коефіцієнт к дискретно змінюватиметься від 1 до 5. За цими двома промасштабованими значеннями у програмі обчислюємо: • са = х-к* а - горизонтальну координату нового положення центра лівої дуги; • сЬ = х + к*а - горизонтальну координату нового положення центра правої дуги (вертикальні координати обох центрів у процесі масштабування не змінюються);
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 283 • R = k*\la2+h2 - спільний радіус обох дуг (за теоремою Піфагора); 180 h • ф = Arctan (—) - початковий кут для лівої дуги в п а градусах; • відповідний кінцевий кут для правої дуги становитиме (180°-ф) ; • кінцевий кут лівої дуги і початковий - правої у нас є постійні і дорівнюють відповідно - 240° і 300°. • вертикальну координату точки Q (її значення дорівнює (Y + b + c)). Величини b і с знаходимо з двох прямокутних трикутників із гострими кутами 30° і 60° (див. рис. 4.8) за відомими тригонометричними формулами: b = R*Cos(3(f) = ^y-; d = R*Sin(30°)=^; c = (a+d)*7g(30°) = (a + d)*?j-. • координати точок з’єднання ліній з крайніми точками обох дуг знайдемо, використовуючи процедуру модуля Graph, tpu: GetAxcCoords(Coords); Параметр Coords - змінна типу Record, яку в описовій частині програми необхідно описати так: Var Coords : ArcCoordsType; Тип ArcCoordsType є вбудованим (стандартним) типом модуля Graph.tpu, який має таку структуру: ArcCoordsType = Record X, Y : Integer; { екранні координати центра дуги} XStart, YStart : Integer; { координати початку дуги} XEnd, YEnd : Integer; { координати кінця дуги} End; За координатами нижніх точок обох дуг і координатами точки Q проводимо дві дотичні, які завершують формування фігури “серце”.
284 4.5. Записи 4.5•6. Програма "пульсуюче серце" Program XIO_Love; {актуальна в День Святого Валентина, і не тільки!)} Uses Crt, Graph; Var X, Y, k, a, h, R, kl, ca, cb, Drv, Drm, L: Integer; Coord : ArcCoordsType; Procedure Serce (a, h, k, x, y, kl : Integer); Var і, j : Integer; Begin Case kl of 1: SetColor (K + L); ' 2: SetColor (L) / End; ca := x - k * a; cb := x + k * a; R := k * Round (Sqrt {Sqr (a) + Sqr (h) ) ) ; OutTextXY (X,Y,'L o v e1); Arc (ca, Y, Round {Arctan {h/a) * 180/Pi), 240, R) ; GetArcCoords (Coord); і := Coord.Xend; j := Coord.Yend; Line (i,j,x, Round (Y+k*a/Sqrt (3)+2*R/Sqrt (3) ) ) ; Arc (cb,Y,300, Round (180 - Arctan (h/a)* 180/Pi), R); GetArcCoords (Coord); і := Coord.XStart; j := Coord.YStart; Line (x, Round (Y+k*a/Sqrt (3)+2*R/Sgrt(3)), i, j); Detlay (6000) End; BEGIN { Write ('Введіть коефіцієнт масштабування k ='); Readln(k) ; % Write ('Введіть ah (a > h) ='); Readln{a, h); Write ('Введіть координати X Y центр, точки ->'); Readln(X, Y); } a := 15; h := 10; L := 15; X := 300; Y := 200; Drv := Detect; InitGraph ( Drv, Drm, 'C:\BP\Bgi' ); SetBkColor(L); SetTextJustifyi 1,1); SetTextStyle(8,0,2); Repeat \ For k : = 1 to 5 do Serce (a, h, k, X + 150, Y, 1) For k : = 5 downto 1 do Serce (a, h, k, X + 150, Y, 2) For k: = ■1 to 5 do Serce (a, h, k, X - 150, Y, 1) For k: = 5 downto 1 do Serce (a, h, k, X - 150, Y, 2) Until KeyPressed END.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 285 4.6. Обертання двовимірних зображень Нехай нам необхідно запрограмувати поворот на кут ф точки Р(Хуу) навколо початку декартової системи координат ХОУ. Нове положення точки позначимо через Рі(хіУі). Завжди існують чотири числа а,Ь,с,сІ - такі, що координати нового положення точки можуть бути обчислені на основі попередніх значень координат х і у шляхом розв’язання наступної системи рівнянь: На рис. 4.9 точка Р(ху) переходить у точку Рі(хі,уі) шляхом обертання її радіус-вектора г на кут <р. і у Знайдемо перетворення координат при переході точки Р у положення РІ. Позначимо символом р кут, який становить радіус- вектор Р з віссю ОХ. Нехай г - довжина радіус-вектора Р, тоді: (4.6.1) Рис. 4.9. Операція обертання точки на кут ф X, = г • cos(<p + P) = r(cos<p • cosp - sin<p • sinp) у, = г • sin (<p + P) = r (sintp • cosp + coscp - sinp) . x у Оскільки cosp = — і sinp = —, то, підставляючи ці вирази в г г
286 4.6. Обертання двовимірних зображень У матричній формі обертання точки Р на кут <р виглядає так: і Уі. СОБф -БІПф БІПф СОБф (4.8.2) Система рівнянь (4.8.2) описує обертання навколо точки О - початку системи координат. Якщо ж нам потрібно виконати обертання щодо будь-якої заданої точки з координатами (хо, у0), то у рівняннях (4.8.2) необхідно Замінити: х на (х - х0), а у - на (у-уо), Хі на (хі - х0) і у і на {у і - у 0). Відбудеться зміщення початку системи координат. Система рівнянь, яка описує обертання точки Р навколо будь- якої точки з координатами (хЛ уо), набуде вигляду: =х0 +(Х-Х0)-С0$<р~(у- УоІ'ЬІПф {уі=Уо+(х-хо)'5ІІІ(Р+(У-Уо)-с05(Р- (4.8.3) Або у матричній формі: Х1 хо + — Уі Уо СОБф -81Пф 8ІПф СОБф х-*о У-Уо. % Приклад: Написати програму, яка демонструє неперервний процес обертання “ракети” навколо певної точки графічного екрана, що має координати (х& у0)- Можливі два варіанти розв’язання цієї задачі. Якщо під час повертання, наступне положення фігури перераховувати на основі координат її точок у попередньому положенні, то через деякий час форм^ фігури почне спотворюватись. Це відбувається внаслідок накопичення похибок, що виникають у процесі перетворення координат. Щоб цього не відбувалось, необхідно зафіксувати початкове положення фігури у масиві Тг. Координати точок фігури для кожного нового кута обертання обчислювати за цим початковим положенням. Правильний варіант програми наведено нижче.
4. ВІЗУАШЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 287 4.6.1. Програма обертання "ракети" Program XIO_Obert; Uses Crt, Graph; Const Tr: Array [1..11] of PointType = ((X:10; Y:10), (X:30; Y:10) , (X:40; Y:20), (X:70; y:20), (X:100;Y:30) , (X:70; Y:40) , (X:40; Y:40) , (X:30; Y:50) , (X:10; у:50), (X:20; Y:40), (X:20; Y:20)); Var TR1 : Array [1..11] of PointType; Drv, Dm, i, j, Nk, xO, yO : Integer; P : Pointer; Alfa : Real; Size : Integer; BEGIN xO := 200; yO := 200; Drv := Detect; InitGraph (Drv, Drm, f C:\BP\BGI1); SetBkColor (White); SetColor (Red); Circle (x0, yO, 1); { Центр обертання } Alfa := Pi / 20.0; For j := 1 to 10000 do Begin SetColor (Black) ; {Що буде, якщо цей оператор прибрати ?} If KeyPressed then Halt; For i:=l to 11 do Begin Trl[i].x:=x0+Round(Tr[i].x*Cos (Alfa)- Tr [i] . y* Sin (Alfa) ) ; Trl [і] . у :=y0+Round(Tr [i] . x*Sin (Alfa) +Tr [i] .y*Cos(Alfa) ) End; Alfa := Alfa + 0.02; SetFillStyle (1, Green); FillPoly (11, Trl); Delay (1000); SetFillStyle (1, Black); FillPoly (11, Trl) End; Repeat Until KeyPressed END.
288 4.6. Обертання двовимірних зображень Щоб обертання фігури відбувалось навколо її геометричного центра, необхідно від абсолютних (екранних) координат перейти до координат відносних, які пораховані відносно геометричного центра (див. рис. 4.10). -20 20 -10 10 20 10 50 0 20-10 -10-10 -20-20 -40-20 -30-10 -ЗО 10. . Рис. 4.10. Відаосні координати Завдання для самостійної, роботи Замініть у програмі хю_оЬед^ цими координатами попередній вміст масиву Тг і запустіть її на виконання.
4. ВІЗУАШЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 289 4.7. Фрактали Наука наприкінці XX - на початку XXI століття відкрила та почала інтенсивне дослідження багатьох нових явищ і нетрадиційних понять. У науковий обіг увійшли терміни хаос, дивні атрактори, вейвлети, синтез та стискання зображень. Вони і* явились завдяки поєднанню зусиль математики, теоретичної фізики, біології, мистецтва та комп’ютерної графіки. Сьогодні комп’ютерні технології дають змогу обчислити і візуалізувати речі, про які раніше не йшлося. Особливе місце тут займає поняття фракталу [12, 52, 63, 68 ]. Фрактали - це геометричні фігури, певна частина кожної з яких повторює у менших розмірах свою загальну форму, тобто підлягає принципу самоподібності. Фрактали представляють собою множину взаємозв’язаних елементів, однакових за структурою, проте відмінних один від одного своїми розмірами. Про такі фігури кажуть, що вони володіють “масштабною подібністю”. Вчені зі здивуванням виявили, що безліч матеріальних об’єктів живої і неживої природи володіють цією самоподібністю, тобто є фрактальними. Фрактали у природі можна спостерігати, починаючи під мікросвіту до космосу. Усвідомлення цього стало справжньою революцією у сприйнятті людиною навколишнього світу. Деякими властивостями самоподібності володіє більшість складних природних систем, що дає змогу вивчати їх, не аналізуючи кожен елемент окремо, а досліджуючи лишень загальні закони взаємодії елементів системи. Науку про фрактали почали називати геометрією XXI століття. Перші дослідження фракталів давали суто естетичне задоволення - спостереження краси, що не приносила практичної користі. Проте детальніше вивчення цих явищ продемонструвало можливість їхнього широкого застосування: • стиснення комп’ютерних картинок на основі врахування фрактальних законів приводить до значно вищої якості наступного відтворення стиснутих зображень - явище пікселізації тут відсутнє; • фрактальне представлення хаотичних турбулентних потоків рідини забезпечує їхнє моделювання у гідродинаміці; 10 7-451
290 4.7. Фрактали • полум’я, як потік плазми, також моделюють цим способом; • у радіофізиці використовують антени фрактальної форми (це зменшує їхні розміри і вагу); • медики вбачають у процесі серцебиття фрактальні закономірності; • географи досліджують берегові лінії суші як фрактальні лінії; • геологи помітили фрактали у кристалічній структурі мінералів. ( Ми спостерігаємо фрактали, розглядаючи листя папороті, сніжинку на рукаві, захмарене небо, дерево (рис. 4.11). їхній вигляд, що повторюється у зменшених деталях, надає цим структурам унікальної форми, яка робить виклик формам класичної геометрії. Літератори стверджують, що фрактали у поезії є також реальністю. Наприклад, такий вірш є фрактальним: Іду я і бачу міст, під мостом ворона мокне, Взяв ворону я за хвіст, положив її на міст, хай вона підсохне. їду я і бачу міст, на мосту ворона сохне, Взяв ворону я' за хвіст, положив її під міст, хай вона помокне... ВідомоіЬ також є притча Чжуан Цзи про метелика, яку можна сформулювати так: (<Притча про філософа, якому сниться, що він є метеликом, якому сниться, що він є філософом, якому сниться, що він є метеликом, якому сниться, що він є філософом ”. Ідея про те, що хаос, взаємопов’язаний із фрактальними траєкторіями, - це порядок, проте порядок дуже складний, лягла в основу музикального редактора РгасіМм 2000, створеного Густаво Діасом Хересом.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 291 Рис. 4.11. Приклади фракталів у природі Вперше фрактали відкрив і розпочав їх досліджувати французький математик Бенуа Мандельброт, який 1924 року народився у Варшаві. У 1936 році його сім’я емігрувала до Парижа. У дитинстві жодного інтересу до навчання Бенуа не проявляв. До шістнадцяти років ледве знав алфавіт і таблицю множення до п’яти. Але після двадцяти років у нього відкрився незвичайний математичний дар Бенуа Мендельброт і прекрасна просторова уява, що дозволило йому успішно закінчити університет Сорбонни. Любов до “чистої математики” привела Мандельброта 1958 року в науково-дослідний центр ІВМ, де він працював у області лінгвістики, теорії ігор, економіки, аеронавтики, географії, фізіології, астрономії та фізики. Досліджуючи економіку, Бенуа Мандельброт побачив, що випадкові, на перший погляд, коливання цін відповідають прихованому часовому математичному порядку, який не описується стандартними залежностями. Тоді він зайнявся вивченням статистики цін на бавовну за понад столітній період часу. Локальні коливання цін здавалися випадковими, але Мандельброт зміг з’ясувати тенденцію їхньої зміни. Він побачив симетрію у тривалих коливаннях ціни і коливаннях короткочасних. Це відкриття виявилося несподіванкою для економістів, адже Бенуа застосував для вирішення цієї проблеми зачатки свого' рекурсивного (фрактального) методу. Поняття “фрактал” (від латинського /гасШв, - роздроблений, розбитий) - його власний винахід. Термін запропоновано Мандельбротом 1975 року для позначення нерегулярних, однак самоподібних структур, якими він займався. Народження фракталь-
292 4.7. Фрактали ної геометрії пов’язують з виходом 1977 року книги Мандельброта “The Fractal Geometry of Nature” - “Фронтальна геометрія природи”, де наведено таке означення: “Фракталом називається структура, що складається з частин, які певним чином є подібними до цілого” [63]. Сьогодні Мандельброт є членом Американської Академії Мистецтв і Наук, Національної Академії наук США. Він має численні почесні наукові ступені і нагороди. Його найважливіша остання нагорода - премія Вольфа^ фізики. Справедливості заради Зауважимо, що фрактальними закономірностями математики цікавились задовго до Мандельброта. У своїх працях він узагальнив результати інших відомих вчених, які працювали у цьому ж напрямі в 1875-1925 pp. (Пуанкаре, Фату, Жюліа, Кантора, Хаусдорфа). Практично всі об’єкти з нечіткою, хаотичною, нерегулярною структурою (а таких в природі переважна більшість) складаються з фракталів. Фрактал - об’єкт, що володіє безмежною складністю, що дає змогу розглядати стільки ж його деталей зблизька, як і здалеку. Земля є класичним прикладом фрактального об’єкта. З космосу вона має форму кулі. З наближенням до неї з’являються океани, континенти, узбережжя і лайцюги гір. Розглядаючи гори ближче, побачимо ще дрібніші деталі: шматочок землі на поверхні гори у своєму масштабі такий же складний і нерівний, як сама гора. І навіть ще сильніше збільшення покаже крихітні частинки ґрунту, кожна з яких сама є фрактальним об’єктом. 4.7.1. Класифікація фракталів * • Геометричні фрактали. Фрактали цього класу є найнаоч- нішими. їх одержують за допомогою деякої ламаної лінії (у двовимірному випадку) або поверхні (у тривимірному випадку), яку називають генератором. За один крок роботи алгоритму кожен із відрізків, що становлять ламану, замінюють на ламану-генератор у відповідному масштабі. Нескінченне повторення цієї процедури формує геометричний фрактал. Розглянемо один з таких фрактальних об’єктів - тріадну криву Гельги фон Кох, яку вона винайшла 1904 р. Побудова кривої розпочинається з відрізка одиничної довжини. З трьох таких
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 293 иідрізків утворено рівноеторонній трикутник (рис. 4.12) - це нульове покоління кривої Кох. Далі кожну ланку замінено на гнірний елемент. Унаслідок цієї заміни виходить наступне покоління кривої Кох. У першому поколінні з однієї лінії утворюється крива з чотирьох прямолінійних ланок, кожна швдовжки в 1/3 від довжини початкової лінії. Для отримання третього покоління проробляються ті ж дії - кожну ланку замінено і ш зменшений твірний елемент. Тобто для отримання кожного наступного покоління, всі ланки попереднього покоління заміняють зменшеним твірним елементом. На рис. 4.12 представлено п’ять поколінь кривої. При п -> оо крива Кох стає фрактальним об’єктом. Якщо ділити кожну зі сторін трикутника навпіл і з’єднувати точки поділу лініями, отримаємо новий фрактал - трикутники Серпінського. Зафарбовуючи їх у різні кольори, можна отримати досить привабливі геометричні побудови (рис. 4.13). Змінимо правила побудови й отримаємо ще один геометричний фрактальний об’єкт. Нехай твірним елементом слугуватимуть два рівні відрізки, з’єднані під прямим кутом. У нульовому поколінні замінимо одиничний відрізок на цей утворюючий елемент так, щоб кут був спрямований угору. Можна сказати, що за такої заміни відбувається зсув середини ланки. Унаслідок побудови Рис. 4.12. Фрактал з назвою “сніжинка Гельги фон Кох” Рис. 4.13. Трикутники Серпінського
294 4.7. Фрактали наступних поколінь виконується правило: найпершу ліву ланку замінюють на твірний елемент так, щоб середина ланки зміщувапася ліворуч від напряму руху, а з заміною наступних ланок напрями зсуву середин відрізків повинні чергуватись. На рис. 4.14 представлено три перші покоління, а на рис. 4.15 - 16-те покоління кривої, побудованої за принципом, описаним вище. Граничну фрактальну фігуру (при п —> об) називають “драконом” Хартера-Хейтуея. Стохастичні фрактали. Ще одним відомим класом фракталів є стохастичні фрактали, які можна отримати у випадку, Якщо в ітераційному процесі випадковим чином міняти будь-які його параметри. У цьому випадку виходять об’єкти дуже схожі на природні - несиметричні дерева, порізані берегові лінії і т.д. Двовимірні стохастичні фрактали використовують при моделюванні рельєфу місцевості і поверхні моря. Алгебричні фрактали. Це найбільша група фракталів. Одержують їх за допомогою нелінійних процесів в ІУ-вимірних просторах. Найбільше вивчено двовимірні процесії. Інтерпретуючи нелінійний ітераційний процес як дискретну динамічну систему, можна користуватися термінологією теорії цих систем: фазовий портрет, встановлений режим, атрактор і т. д. Відомо, що нелінійні динамічні системи володіють декількома стійкими станами. Той стан, в якому опинилася динамічна система після певного числа ітерацій, залежить від її початкового стану. Тому кожен стійкий стан (атрактор) володіє деякою областю початкових станів, з яких система обов’язково потрапить у зазначені кінцеві стани. Отже, фазовий простір системи Рис. 4.14. Перші три кроки побудови “дракона” Хартера-Хейтуея Рис. 4.15. Результат 16-ти кроків побудови
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 295 розбивається на області притягання атракторів. Якщо фазовим є двовимірний простір, то, зафарбовуючи області притягання різними кольорами, можна отримати різнокольоровий фазовий портрет' цієї системи (ітераційного процесу). Змінюючи алгоритм иибору кольору, можна отримати складні фрактальні картини з химерними багатоколірними узорами (рис. 4.16, рис. 4.17). Можливість, за допомогою примітивних алгоритмів, породжувати дуже складні нетривіальні структури стала несподіванкою для математиків. Приклад. Написати програму, яка будує фрактал Мандельброта. Найвідомішим фракталом у світі є алгебрична множина Мандельброта (рис. 4.18). Це класичний приклад фрактала з часовим порогом. Точки, з яких він складається, зображено на комплексній площині, яка дуже подібна на систему координат Оху. Однак, якщо на звичній координатній площині зображають дійсні числа, то комплексна площина містить комплексні числа, які мають дійсну та уявну частину. Це цілковито “перевертає” звичні правила математики і приводить до дуже незвичайних результатів. Для кожної точки на екрані комп’ютер здійснює серію обчислень, використовуючи відповідну точку на комплексній площині. Координати точки записують у просте рівняння, за яким визначають нову пару координат. Ці координати підставляють знову в те ж рівняння і виходить ще одна пара координат. Повторюючи цей процес багато сотень разів, одержуємо набір координат, що визначає уявний шлях - орбіту. Хоча ця орбіта цілковито розташована в комплексній площині (має два виміри, а Рис. 4.16. Фрактал йгипк_йиск Рис. 4.17. Фрактал FANTAZY (http://www.fractal.cdu.edu.ua/gal.php)
296 4.7. Фрактали не три), вона виглядає так, неначе підноситься над площиною для кращого зорового сприйняття. Рис. 4.18. Фрактал Мандельброта Якщо орбіта точки ніколи не виходить з циліндра певного діаметра, розташованого на початку координат комплексної площини, то вважають, що ця точка - елемент множини Мандельброта. Точки, які задовольняють цьому критерію, зазвичай, зафарбовують чорним кольором. Якщо орбіта точки “утікає” з циліндра, то відповідному пікселу приписують колір, який відображає кількість точок орбіти, обчислених перше,* ніж ця точка вийде з циліндра. Проміжок часу, необхідний для виходу орбітальних точок з циліндра, називають часом тікання (escape-time). Коли цю процедуру застосувати до кожного піксела, на екрані згенерується різноколірне зображення множини Мандельброта. Змінюючи рівняння для розрахунку орбіт, однак залишаючи загалом вже описаний метод, одержимо інші складні, деталізовані фрактали з часовим порогом. 4.7.2. Алгоритм побудови фрактала Мандельброта Цей алгоритм є достатньо простим. Його засновано на ітеративному виразі: zM=z2i+c,
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 297 де 2І і С - комплексні змінні. Ітерації виконуються для кожної стартової точки, що належить прямокутній або квадратній області - підмножині комплексної площини. Ітераційний процес продовжують доти, доки 2І не вийде за межі кола радіусу 4, центр мкого розташований у точці (0,0) - це означатиме, що атрактор динамічної системи прямує до нескінченності, або після достатньо великої кількості ітерацій, (наприклад, 200-500) 2І збігатиметься до деякої точки кола. Залежно від кількості ітерацій, протягом яких 2{ залишалася всередині кола, можна встановити колір точки С (якщо 2І залишається усередині кола протягом достатньо великої кількості ітерацій, ітераційний процес припиняється і цій точці площини надається чорний колір). Вищеописаний алгоритм дає наближення до так званої множини Мандельброта. Цій множині належать точки, які впродовж нескінченної кількості ітерацій не прямують до нескінченності (точки мають чорний колір). Точки, що належать межі множини (саме там виникають складні структури), прямують до нескінченності за скінченну кількість ітерацій, а точки, що лежать за межами множини, прямують до нескінченності через декілька ітерацій (білий фон). Фрагменти фрактала Мандельброта при різному збільшенні подано на рис. 4.19. Рис. 4.19. Фрагменти фрактала Мандельброта при різному збільшенні Множину Мандельброта будують шляхом ітераційного процесу над комплексним відображенням: 2М <— 2^ + С, де 2 = х + і у, а С = р + ід, де і - >/—Т. Наш процес зводиться до ітерацій над системою дискретних відображень типу:
298 4.7. Фрактали *м=А*і,Уі,р) - у прямокутній області. Ум = Ахі,Уі>Ф Послідовно перебираємо всі точки С, зафарбовуючи їх різними кольорами залежно від/того, який результат роботи над ними ітераційного процесу. /Можна встановити певний колір зафарбовування (наприклад, (чорний) залежно від того, як довго послідовність ітерацій залишалась усередині коло певного радіуса для заданого С. Самі ітерації набудуть вигляду: (хо>.Уо) (хі>Л) (хі>Уі) • Процес побудови полягає у наступному: обирають фіксовану точку з координатами (х, _у) і простежують її долю за різних значень параметрів. Результати наносять на графічний екран точка за точкою. Після завершення ітерацій отримують таке зображення, як нарис. 4.18. Перепишемо наше відображення так: хм=хі2~Уі2+Р yi+l=2x,yt+q. Встановимо відповідність між кольором і часом, за який точка (х,у) прямує до нескінченності. Нехай (А * В) - розміри екрана. У нас А = 640, В = 480, тобто роздільна здатність екрана - (640*480) пікселів. Нехай його можна розфарбувати у різні кольори, кількість яких К + 1, де К = 0 - чорний колір. У нас К = 16. Алгоритм побудови фрактала Мандельброта налічує такі кроки: Крок 0. (Ініціалізація). • Описати два одновимірні масиви Р і Q з елементами дійсного типу (бажано Extended), які міститимуть певні дані для пар координат усіх пікселів графічного екрана. Кількість елементів масиву Р = 641, а кількість елементів Q = 481. • Обрати значення Хтіп, Xmax, Ymirt, Ymax. Наприклад: Хтіп = -3.3, Хтах = 2.25; Ymin = -2.1; Ymax = 2.1.
4. ВІЗУАШЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 299 • Обрати велику кількість ітерацій: М = 300. • Обчислити (IX = (Хтах - Хтіп) / (А- 1), dY = (Ymax - Ymin)/(B - 1). • Двома циклами заповнити масиви Р і Q значеннями: Р[0]=Хтіп; Р[і+1] = Р[і] + dX;i = 0+A; Q[0] = Ymin; Q[i+1] =Q[iJ + dY; і = 0 +B. Крок 1: Запустити зовнішній цикл For пікселами горизонталі екрана, змінюючи параметр циклу Nx від 0 до А-1, у якому доцільно передбачити його завчасне завершення на вимогу користувача: If KeyPressed then Halt; . Крок 2: Запустити внутрішній цикл For вертикальними пікселями екрана, змінюючи параметр циклу TVy від 0 до В-1, всередині якого: • Занулювати дві змінні дійсного типу X і Y. • Встановити лічильнику ітерацій і значення, що дорівнює 1. • Запустити ітераційний цикл Repeat, у тілі якого: Обчислити R=X*X+ Y*Y Y=2*X*Y+Q[Ny]; X=X*X-Y*Y+P[NxJ; Збільшити лічильник і на І (і := і +1). Крок 3 {оцінка): Якщо і < М або R < М - продовжити виконання циклу Repeat, інакше якщо і = К - обрати колір 0 (чорний) і перейти на крок 4, інакше обирати колір з номером і й перейти на крок 4. Крок 4: Встановити обраний колір піксела з координатами (/Vx, Ny) і перейти до наступної точки, починаючи з кроку 1.
300 4.7. Фрактали 4.7.3, Програма побудови фрактала Мандельброта Program Xio_Mandelbrot; {Побудова фрактала Мандельброта } {$N+) { Директива, яка вмикає математичний копроцесор } Uses Crt, Graph; Const A = 640; В = 480; К, = 16; M = 300; Var Р ; Array [0..640] of Extended; Q : Array [0..480] of Extended; XMax, YMax, XMin, YMin : Extended; R, dX, dY, X, Y, X2, Y2 : Extended; i, Nx, Ny, Drv, Drm : Integer; BEGIN Drv := Detect; InitGraph (Drv, Drm, 'С:\BP\BGI1); XMin := -3.3; {Крок 0: Ініціалізація} XMax := 2.25; YMin := -2.1; YMax := 2.1; dX := (XMax - XMin) / (A - 1); dY := (YMax - Ymin) / (B - 1); Q [0] := Ymin; For і := 0 to В - 1 do Q [i+1] := Q [i] + dY; P [0] := XMin ; For і := 0 to A - 1 do P [i+1] := P [i]+ dX; For Nx := 0 to A-l do {Крок 1} Begin If Keypressed then Halt; For Ny := 0 to B-l do {Крок 2} Begin X := 0.0; Y := 0.0; і := 1; Repeat K2 := X * X; Y2 := Y * Y; R :=X2 + Y2; Y :=2*X*Y+Q [Ny]; X := X2 - Y2 + P [Nx]; і := і + 1; Until ( і >= M) or (R > M) ; {Крок 3} If і = k then {Крок 4} PutPixel (Nx, Ny, 0) else PutPixel (Nx, Ny, i) End End; Repeat Until KeyPressed END.
4. ВІЗУАЛІЗАЩЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 301 4.7.4. Програма побудови фрикутника Серпінського Етапи побудови трикутника Серпінського проілюстровано на рис. 4.20. Program XIO_Serpinsky; {$N+} { Директива, яка вмикає математичний копроцесор } Uses Crt, Graph; Var Drv, Drm : Integer; Procedure Tryk (x, y, s : Integer); Var Sd2 :Integer; Begin Sd2 := s div 2; $ Randomize; If s>= 2 then Begin If Keypressed then Halt; Setcolor ( Random (15) +1 ); Tryk (Hound(x-Sd2) , Hound(y+Sd2*0 . 449025) , Round(Sd2) ) ; Tryk(Round(x+Sd2), Round(y+Sd2*0.449025), Round(Sd2)); Tryk(Round(x), Hound(y-Sd2*l.283025), Hound(Sd2)); Line(x-Sd2,Round(y-s*0.417), x+Sd2,Hound(y-s*0.417 )); ! Line(x+Sd2,Round(y-s*0.417), Round(x),Hound(y+s*0.417)); Line(Round(x),Hound(y+s*0.417),x-Sd2,Hound(y-s*0.417)) * End End; BEGIN Drv := Detect; # Initgraph (Drv, Drm, 1C:\BP\BGI1); / Line (88, 425, 554, 425); Line (88, 425, 320, 24); Line (320, 24, 554, 425); Tryk (320, 320, 240); Repeat Until Keypressed END. Рис. 4.20. Фотографії етапів побудови трикутника Серпінського програмою ХІО_8егріпвку, за умови ^ б >= 1 ЬЬеп
302 4.8. Файли 4.8. Файли Файли - це впорядковані набори даних, компоненти яких взаємозв’язані логічно. У мови програмування файлові типи даних введено для роботи із зовнішніми щодо оперативної пам’яті (ОП) пристроями - дисками, портами, принтерами і т.д. Надсилання даних із зовнішнього пристрою в ОП називається читанням, або введенням; зворотний процес - записом, або виведенням. Файли використовують для: • довготривалого зберігання даних; • для забезпечення обміну даними між різними програмами; • для тимчасового зберігання проміжних результатів. При використанні файлів у програмі (як джерела вхідних даних або місця для запису результатів) розрізняють файли логічні і фізичні. Логічний файл - поняття динамічне. Це дані у процесі їхнього створення і передавання. Ми вводимо з клавіатури файл даних, які на момент введення існують тільки у нашій голові. Між двома комп’ютерами, об’єднаними у локальну мережу, відбувається передавання файла даних мережевим кабелем. Користувач друкує на принтері текстовий файл. На моніторі з допомогою графічного редактора створюється файл рисунка. Напругу живлення комп’ютера раптово вимкнули і файл зник назавжди. Все це приклади логічних файлів. Якщо створений нами текст або рисунок записати на магнітний чи оптичний носій, ми отримаємо фізичний файл. Він має певну адресу на диску, займає відповідний об’єм поверхні носія. Його компоненти зберігаються у деякому, наперед заданому, форматі (стандарті). Кожна операційна система підтримує один або декілька стандартів зберігання файлів, які називають файловою системою. Перше покоління сім’ї операційних систем (ОС) ЛШ-сумісного ПК, які мали абревіатуру DOS {Disk Operation System), підтримувало файлову систему із назвою FAT-16. У версіях WINDOWS 95/98/МЕ її змінила оптимальніша система FAT-32. WINDOWS NT 4.0 обох перелічених систем не підтримує. Його “рідною”
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 303 файловою системою є NTFS. Наступні версії ОС WINDOWS 2000 № АР дають змогу працювати як із FAT-32, так і з NTFS. Файли можуть містити в собі дані різного призначення, а саме: • програми, готові до виконання під управлінням операційної системи (виконувані файли); • файли з даними для цих програм; • тексти цих програм. Рисунки, фотографії, музику, фільми також зберігають у формі дискових файлів. Виконувані файли можуть запускатися під управлінням ОС на виконання, а вміст невиконуваних файлів може змінюватись у процесі виконання програм. 4.8.1. Фізична будова та логічна організація вінчестера Жорсткий диск (ЖД), або вінчестер, сконструйовано із декількох круглих металевих пластин, покритих магнітним матеріалом, та головок для здійснення операцій читання-запису із механізмом їхнього позиціонування над поверхнею пластин. Все це поміщено у щільний металевий прямокутний корпус. До останнього прикріплено друковану плату з контролером і буферною пам’яттю (кешем), яка за допомогою 40- або 80-жиль- мого шлейфа з’єднується з материнською платою чи окремим контролером. Перший накопичувач на ЖД розроблено на фірмі IBM на початку 70-х років. Цей чотирнадцятидюймовий диск містив по 30Мб інформації на кожній стороні, що слугувало приводом щодо його назви, оскільки об’єм диска 30/30 і перекликався з назвою відомої рушниці фірми Winchester. Серійний накопичу вач на ЖД - 3340 - створено фірмою IBM 1973 року (місткість 140Мб, вартість - $ 8600). Такі пристрої призначалися для використання на універсальних ЕОМ у ролі зовнішньої магнітної пам’яті. Принцип дії магнітної пам’яті заснований на збереженні протягом тривалого часу групою сусідніх магнітних доменів однакової орієнтації, підтримуваної за рахунок їхнього сумарного магнітного поля. Початкова орієнтація доменів досягається завдяки впливові магнітного поля записуючої головки. Під час зчитурання в обмотку головки подається струм, який посилюється при проходженні над ділянкою доменів, орієнтованих за напрямом струму
304 4.8. Файли підмагнічування, і послабляється при проходженні головки над ділянкою доменів, орієнтованих у протилежному напрямі. Електронними схемними засобами можна чітко фіксувати рівень струму в обмотці головки, що читає, на межі ділянок доменів із різною орієнтацією. Отже, під час записування на магнітний носій двійкових даних його намагнічена поверхня модулюється так, щоб за зміною намагніченості можна було\ відновити двійковий код, виконуючи при цьому мінімальну кількість перемикань. Магнітну частину поверхні кожної із металевих пластин вінчестера умовно розділено на концентричні доріжки, а доріжки розділено на сектори. Доріжки, розташовані на рівній відстані від центра по всіх поверхнях пластин, об’єднують у циліндри (рис. 4.21). Для читання певного сектора даних диска (його об’єм, зазвичай, дорівнює 512 байт) потрібно: • підвести головки на потрібну відстань від центра, тобто поставити їх на потрібний циліндр; • розпочати перегляд доріжки на потрібній пластині (активізувати потрібну головку); • здійснити читання всієї інформації до появи заголовка сектора, номер якого (а він міститься в цьому заголовку) збігається з номером, необхідним для операції читання або запису. Відповідного такої схеми метод відшукання необхідної інформації на ЖД називають CMS-адресацією (Cylinder-Head-Sector). Виконання перелічених операцій забезпечує BIOS (базова система уведення- виведення), яка містить набір системних функцій, серед яких - програма читання-запису даних на жорсткому диску. Для отримання вмісту одного сектора необхідно подати його СНЇ-адресу. Кількість секторів, циліндрів і головок нашого диска процедури BIOS’ у визначають попередньо. Для цього існує режим AutoDetect в Setup. ^~Цил'тір ' - і ОрІЖНй Рис. 4.21. Елементи жорсткого диска
4. ВІЗУАШЗАІДЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 305 Однак інформація про геометрію, яку використовують для роботи функцій доступу до диска, навіть близько не відповідає реальній геометрії сучасного жорсткого диска. Він налічує до трьох пластин, одна з яких може використовуватися тільки з одного боку, та 1-6 головок. Отож, контролер ЖД здійснює трансляцію адрес, що надходять до нього. Таку ж трансляцію виконує і BIOS, працюючи за механізмом LBA (Logical Block Addressing). Відповідно до ідеології ОС MS DOS, ЖД може складатися з так званих “розділів” - незалежних областей диска, побудованих за схемою будь-якої ОС, і використовувати будь-яку файлову систему. Таких розділів повинно бути два - головний (Primary), з якого, зазвичай, здійснюється завантаження ОС, і розширений (Extended), який, за необхідності, можна розділити на декілька частин-підрозділів (логічних дисків). Отже, перший розділ диска самостійний, інші об’єднані в групу. Кожен розділ належить до тієї чи іншої файлової системи і має назву однієї із послідовності великих літер латинського алфавіту: С, D, Е і т. д. 4.8.2. Системні сектори Найперший сектор ЖД має назву MBR (Master Boot Record). Він містить дві частини - програму початкового завантажувача і таблиці розділів диска DPT (Disk Partition Table). DPT налічує чотири записи, що позначають адресу початку розділу, його розмір у секторах, адресу кінця і тип файлової системи. Зазвичай, використовується тільки два записи - для головного і розширеного розділу, оскільки кожен підрозділ (логічний диск) має таку ж DPT з зазначенням адреси наступного підрозділу. Завдання завантажувача, що є в MBR - передбачити завантаження ОС з потрібного розділу. Це даватиме змогу використовувати декілька незалежних ОС. Стандартний завантажувач DOS надає вельми обмежений механізм вибору - завантаження можливе з того розділу, в якому встановлено прапорець активності таблиці DPT. Перший сектор кожного розділу називають Boot Sector. Він налічує також завантажувальну програму і таблицю BIOS Parameter Block, ВРВ. У цій таблиці подано інформацію щодо місцезнаходження та розміру іншої важливої області - індексного файла. У FAT16/FAT32 його називають таблицею розташування
306 4.8. Файли файлів FAT {File Allocation Table), у файловій системі NTFS - головною таблицею файлів є MFT {Master File Table). Тут міститься необхідна ОС вичерпна інформація про кожен файл на ЖД (зокрема, ім’я файла, його розмір, місцезнаходження, час і дата створення, а також права доступу до файла). Індексний файл - це перша ділянка, куди передається запит щодо файла. Якщо індексний файл розташовано на ЖД послідовно, пошук необхідних файлів і доступ до них здійснюватиметься значно швидше. За своїм змістом FAT - це великий масив, кожен елемент якого відповідає кожному кластеру. Кластер - блок секторів (від 5-ми до 128-ми), елемент розподілу всього дискового простору кожного розділу. Кожному файлові під час його створення надається необхідна кількість кластерів. Номер першого кластера вносять у каталог (директорію, папку, що є те ж саме), а відповідний цьому кластеру елемент FAT містить номер другого кластера. Елемент FAT' що відповідає другому кластеру, містить номер третього кластера і т.д. Загалом FAT сформовано з таких ланцюжків {Chains). Якщо елемент FAT не належить жодному ланцюжку і не дорівнює 0, його вважають “втраченим” {Lost Cluster). “Втрата” кластерів відбувається внаслідок раптового перезавантаження комп’ютера у момент запису ланцюжка в FAT (наприклад, під час створення/зміни файла, коли операція запису переривається). Зазвичай, це не найстрашніші наслідки несподіваного перезавантаження, однак втрачати місце на диску не дуже хочеться. Якщо файл * згодом збільшується у розмірах, йому призначають нові кластери з числа вільних. Найчастіше вони розташовані в іншому місці диска. Ланцюжок “перестрибує” інші ланцюжки, диск стає фрагментованим, сповільнюючи процес читання даних з фрагментованих файлів. Це усувають програми- дефрагментатори. Вони переносять файли так, щоб їхні кластери розташовувались один за одним. Хоча система ланцюжків є достатньо ефективною і простою, вона налічує недоліки. Перелічимо їх: • Низька надійність. За умови зникнення одного елемента файл загалом буде нечитабельним, а псування FAT означає втрату значної кількості (якщо не всіх) файлів. З метою запобігання цих втрат на ЖД передбачено дві копії FAT.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 307 • Якщо розмір файла не кратний розміру кластера, утворюється слек (Slack) - частина кластера, не зайнята корисною інформацією. Чим більшим є розмір кластера, тим більшу частину диска займає слек. Для файла завдовжки 1 байт затрачається весь кластер. Якщо він має великий розмір (наприклад, 32Кб), то втрати на слек можуть становити 30-50% від загального об’єму диска. 4.8.3. Класифікація файлів З огляду на форми представлення даних файли класифікують на текстові і двійкові. Текстовими файлами називають файли, в яких інформаційними символами слугують символи з шістнадцятковими кодами 20h-7Eh (32-126 - десятковими) і 80h-7Eh (128-254 - десятковими). Серед усіх текстових файлів виокремлюють підмножину “чистих” ЛЛ’СЯ-файлів з символами літер абетки, тобто інформаційні символи яких мають тільки коди з номерами 20h-7Eh. Двійкові (бінарні) файли - це послідовність з будь-яких символів. їхню довжину визначають із заголовка файла. Розділення файлів на текстові та двійкові є важливим, оскільки призначення та обробка бінарних і текстових файлів в. різних ОС відрізняються. Можна ще поділяти файли на: головні, присутність яких є обов’язковою для роботи ОС чи прикладних програм; службові, що містять конфігурацію і параметри головних файлів; робочі, вміст яких змінюється в результаті роботи головних програмних файлів і власне задля яких створюють усі інші файли; тимчасові, що генеруються у момент обробки головних файлів, з метою збереження проміжних результатів. 4.8.4. Файли і каталоги На ЖД існує різновид файла, який називають по різному: каталог (Catalog), директорія (Directory), тека (Folder). Останній термін є найновішим. Його застосовують в ОС із графічним інтерфейсом (GUI). Каталог об’єднує посилання на групу файлів, яка з ним взаємозв’язана. Оскільки посилання на ці файли містить лише один каталог, у користувача складається враження, ніби вони
308 4.8. Файли розташовані в окремому каталозі. Насправді, зазвичай, усі файли перебувають у різних секторах диска, що видно лише на фізичному рівні з допомогою спеціальних сервісних програм, а на рівні представлення даних файли розташовані у каталогах. Каталоги є списками імен файлів та інших каталогів, які є внутрішніми для цього каталогу. Вони налічують вказівники на місцезнаходження файлів і надсилають індексному файлові інформацію, де шукати конкретний файл. Поняття каталогів з’явилося не відразу і не в усіх ОС. Вони виникли там, де передбачали збереження значного об’єму інформації (наприклад, у файлових системах ЖД) і, отже, було складно організувати та розмістити значну кількість файлів. Іноді користувачам доводиться працювати з різними за змістом та однаковими за іменами файлами. Логічно було б розташувати файли кожного користувача в окрему директорію. Проте з’ясувалося, що директорії можна використовувати не тільки для розділення дискового простору між користувачами. За їхньою допомогою можна систематизувати дані на ЖД і змінних носіях. Так виникла друга назва директорії - каталог. В МБ каталоги введено з версії 2.0. 4.8.5. Параметри файлів Будь-який фізичний файл налічує певну службову інформацію. Це ім’я файла, дата і час його створення та модифікації, розмір та інші атрибути, залежні від версії файлової системи. Те саме стосується і каталогу. Ім’я і тип будь-якого файла (чи каталогу) повинне бути унікальним в межах того каталогу, в якому вони розташовані. Розглянемо обмеження, що накладаються на файли операційними системами. 4.8.6. Особливості ЕАТ16 Ім’я файла у цій файловій системі налічує не більше, ніж вісім символів, множину яких наведено у таблиці 4.10. Окрім того, у файлових систем програмних продуктів фірми Microsoft існує так зване розширення, відокремлене від імені файла крапкою. Це розширення неявно зазначає, якою програмою створено чи оброб-
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 309 литиметься певний файл. В МБ ООБ розширення може містити від нуля до трьох символів. Таблиця 4.10 Символи, які застосовують для формування імені та розширення файлів в МУ РОБ Тип символів Позначення Великі та малі латинські літери А-7і а-г Цифри 0-9 Службові символи: Примітка: М5 ВОБ не розрізняє великих і малих літер. Під час виведення імені всі літери перетворяться у малі. В М8 ООБ розширення відіграють важливу роль. Наприклад, розширення виконуваних файлів МБООБ наведено у табл. 4.11. Таблиця 4.11 Розширення виконуваних файлів Розширення Ознака файла .сот Двійковий виконуваний під МУ РОБ файл. Не має заголовка. Максимальний розмір - 64 КБ ехе Двійковий виконуваний під управлінням МУ РОБ або МУ Шп(Іош файл. Містить заголовок. Не має обмежень на довжину Ьаі Командний файл МУ РОБ. У ньому записується послідовність назв програм, які необхідно виконати під управлінням МУ РОБ На імена файлів в ОС МБВОБ, окрім обмежень на довжину і тип символів, накладено додаткові обмеження. Наступні імена файлів зарезервовані за зовнішніми пристроями. Таблиця 4.12 Зарезервовані імена МУ РОБ Ім’я Пристрій ЬРТІ- ІРТ4 Пристрої, під’єднані до паралельних портів комп’ютера. Цифра позначає номер порту РШ Синонім ЬРТІ. Зазвичай, до цього порту під’єднують принтер СОМ1- СОМ8 Пристрої, під’єднані до послідовних портів комп’ютера. Цифра позначає номер порту лих Синонім СОМІ. Зазвичай, до нього під’єднують модем або мишу СОМ Консоль. При виведенні символів - це екран монітора, а при введенні - клавіатура ЖЬ Порожній пристрій. Усі операції введення-виведення на цей пристрій ігноруються. Під час читання з цього пристрою видається символ закінчення файла, а під час записування символи зникають, однак програма отримує повідомлення про успішне виведення
310 4.8. Файли Наведені вище імена пристроїв не можна використовувати як імена файлів. Проте застосовувати їх як розширення - допустимо! Приклади. PRN.txt - неприпустиме ім’я файла. ТЕХТ.ргп, NEW.aux - допустимі імена файлів. Оскільки каталог є одним із видів файла, то на його імена діють ті ж обмеження, що і на файлові. Ім’я каталогу також може мати розширення, проте тут воно не має жодного смислового навантаження і слугує лише доповненням до імені. 4.8.7. Особливості FAT32 Вперше FAT32 з’явилася в ОС Windows 95. Вона дуже подібна на файлову систему FAT16. Для користувача істотними вважають такі її відмінності від FAT16: 1.У FAT32 немає обмежень на кількість літер і розмір розширення. Ця файлова система може налічувати декілька розширень, що розділяються крапкою. Проте тип файла визначають за останнім розширенням, а інші розглядають як ім’я файла. 2. Максимальна довжина імені файла - не 8 символів, як в FAT16, а 255. Отож, не потрібно скорочувати імена файлів, щоб укластися у вісім символів. 3. Ім’я файла в цій файловій системі зберігається у декількох місцях. В одному з них зберігається істинне довге ім’я файла в кодуванні Windows, а в іншому - скорочене до восьми символів ім’я файла в кодуванні DOS. Це передбачено з метою сумісності зі старими версіями FAT. FAT12 і FAT16. Саме вони і лише вони доступні в ОС MS DOS, PC DOS і DR DOS, а також в операційній оболонці Windows ЗЛІ. Опишемо процес утворення цього імені: 3.1. Довге ім’я перетвориться у кодування OEM (в “рідне кодування* MS DOS). 3.2. Якщо ім’я файла вже задовольняє вимоги DOS, то подальші перетворення не провадять. У протилежному випадку - перехід до пункту 3.3. 3.3. Довге ім’я переводиться у верхній регістр. Наприклад, файл aba txt стає ABC. TXT. 3.4. Якщо після цього ім’я файла задовольняє вимогам DOS, то воно і слугуватиме коротким ім’ям. В іншому випадку - перехід до пункту 3.5.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 311 3.5. З довгого імені видаляють усі пропуски, а символи “+”, "“;”, “=”, “[“ і “]”, неприпустимі у довгих іменах, замінюють символом підкреслення 3.6. Якщо в імені є крапки, то частину імені за останньою з них розглядають як розширення. Розширення обрізують справа до трьох символів. Усі крапки з імені, окрім останньої, виокремлють. 3.7. Якщо довжина імені файла, як і раніше, перевищує 8 символів, то отримане ім’я скорочують до шести символів. Виходить “укорочене” ім’я. 3.8. До цього “укороченого” імені додають порядковий номер, записаний через тильду Приклад: Ім’я MyDocuments буде перетворене на MYDOCU-1. 4. В іменах файлів передбачено додаткове використання таких символів: а) пропуски; б) символи + .,: = []; в) усі символи національних алфавітів і псевдографіки. Проте заборонено використовувати управляючі символи і символи: / \ : * ? 11 < > І. 5. У довгих іменах різниця між великими і малими літерами зберігається - це дає змогу полегшити читання файлів. Проте в одному каталозі неприпустимо застосовувати імена файлів, що розрізняються тільки регістром (тобто рядковими і прописними літерами) і більше нічим! Це пояснюється алгоритмом перетворення довгих імен до коротких (див. пункт 2). Іншими словами - в одному каталозі не можуть перебувати водночас два файли або каталоги з однаковими короткими іменами. 6. Довжина повного імені не може перевищувати 260 символів. 7. При копіюванні файлів з VFAT в FAT16 і, передусім, у FAT 12 довгі імена наче “маскуються”, записуючись в області заголовка файла, що, здебільшого, не бере участі у функціонуванні файлової системи. Проте програми, що працюють з файлами на дещо нижчому рівні - програми оптимізації файлів на диску, резервного копіювання, деякі архіватори, деякі антивірусні програми, а також усі програми, що використовують для відкривання файлів метод “управляючих блоків” можуть стерти цю інформацію,
312 4.8. Файли внаслідок чого довгі імена буде втрачено. А втрата довгих імен може призвести до серйозного збою у програмах. Примітка. Якщо використовування застарілих програм уникнути не вдається, необхідно при створенні файлів вживати короткі імена. Можна створювати і довгі імена, проте намагатись значущу частину імені розташовувати у його перших шести символах. 4.8.8. Файли у Pascal-програмах У програмі з кожним файлом з’єднана певна змінна, ім’я якої обирають за правилами побудови ідентифікаторів мови Pascal, і зазначають в описовій частині програми. Іншими словами, перед використанням файла його необхідно описати. Програмне ім’я файла називають файловою змінною (ФЗ) або логічним іменем файла. Мова ВР розрізняє файли трьох видів: типізовані, нетипізо- вані і текстові. Два останніх види є стандартними. Типізований файл створює програміст. Описи файлів Подамо для прикладу описи трьох видів файлів. Опис типізованого файла: Var сім' я ФЗ^ : File of <тип компонент>; . Опис нетипізованого файла: Var < ім'я ФЗ > : File; . Опис текстового файла. Var < ім' я ФЗ > : Text; . Тип компонент типізованого файла може бути стандартним (окрім файлового) або створеним програмістом. Наприклад. Var Fv : File of Real; {Опис типізованого файла із компонентами дійсного типу} Fn : File; {Опис нетипізованого файла} Ft : Text; {Опис текстового файла}.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 313 Текстові файли призначені для зберігання інформації у формі рядків символів. Під час виведення у текстовий файл дані перетворюються з внутрішньої форми представлення у символьну, зрозумілу людині. Під час введення виконується зворотне перетворення. Нетипізовані і типізовані файли містять дані у тій же формі, якої вони набувають в ОП. Відкривання/закривання файлів Наявність тільки опису файла ще не передбачає початку роботи з ним. У виконуваній частині програми спочатку необхідно виконати™ дві дії: • пов’язати описану нами ФЗ (логічне ім’я файла) із певним фізичним файлом на диску; • відкрити цей файл або для читання, або для запису. Перша дія полягає у виклику процедури: Assign (сім'я Ф3>, <повне ім'я фізичного файла>); . Якщо файл розташований у поточному каталозі, то другим параметром процедури Assign записуємо його ім’я з розширенням. Наприклад'. Assign (Fn , ' Dani .dat') ; . Для роботи з файлом, який належить до іншого каталогу, разом із іменем файла зазначаємо шлях до нього, що й буде його повним іменем. Наприклад'. Assign (Fn ,' С: \Temp\Dani.dat') ; . Процедура Assign може приєднувати декілька різних файлів. З цією метою в описовій частині програми необхідно описати змінну: Var Name File : String[ 20] ; Це даватиме змогу присвоїти цій змінній різні імена файлів. Наприклад: NameFile := 'C:\Rob\Data.xy'; Assign (Fn, NameFile); При виконанні другої дії можливі такі ситуації:
314 4.8. Файли 1) фізичного файла з іменем, зазначеним у процедурі Assign, ще не існує і його необхідно створити; 2) такий файл уже є, проте дані, що зберігаються у ньому, необхідно перезаписати; 3) фізичний файл існує і до нього необхідно або дописати чергову порцію даних, або виконати читання даних з нього. У перших двох випадках використовуємо стандартну процедуру: Rewrite ( <ім'я Ф3> ); Вона створить новий чи очистить існуючий файл і підготує його до запису. У третьому випадку використовуємо процедуру: Reset ( <ім' я Ф3> ) ; . Дискові файли у IBM-сумісних ПК не мають іншого обмеження на кількість елементів, окрім розміру вільного простору диска, на якому зазначений файл розташований. Доступ до файлів може бути послідовним (черговий елемент можна прочитати/записати тільки після аналогічної операції з попереднім елементом) і’прямим (виконується читання/запис будь- якого елемента за заданою адресою). Текстові файли дають змогу виконувати тільки послідовний доступ, у нетипізованих і типізованих файлах можна використовувати обидва методи. Операції з файлом типу читання/запис виконуються відомими нам процедурами введення/виведення: Write, Writeln, Read, Readln, першим параметром у яких є ФЗ того файла, над яким ці операції необхідно виконувати. Відсутність цієї змінної у попередніх операторах введення/виведення легко пояснити. Це стандартні імена логічних файлів: Input - для введення з клавіатури; Output - для виведення на дисплей. За відсутності першого параметра компілятор приймає його за замовчуванням. Отже, сформулюємо послідовність дій, які необхідно вико- нати при роботі з файлом у Раяся/-програмі: • описати ФЗ; • пов’язати її з фізичним файлом;
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 315 • відкрити файл для читання і/або запису; • виконати операції уведення/виведення; • закрити файл, запустивши на виконання процедуру: close (сім'я фз> ); Зауважимо, що процес обміну даними між оперативною шім’яттю та диском здійснюється не безпосередньо, а через буфер спеціальну область ОП, виокремлену для кожного відкритого файла. Під час запису у файл вся інформація спочатку потрапляє в Ауфер і там накопичується доти, доки буфер не заповниться. Тільки після цього або після спеціальної команди скидання вмісту буфера иідбуваєгься пересилання даних на зовнішній пристрій. Читання з файла відбувається так: спочатку дані прочитуються в буфер, причому даних прочитується не стільки, скільки запрошується, а скільки поміститься в буфер. Для переміщення по компонентах файла існує поняття файлового вказівника. Логічні пристрої Для роботи з логічними файлами у мові ВР передбачено спеціальні імена пристроїв введення/виведення. Усі вони відіграють роль потенційних джерел або приймачів даних: CON - визначає логічний пристрій - консоль. Для читання даних - це логічне ім’я клавіатури, а для виведення даних - це дисплей. PRN - логічне ім’я принтера. У сучасних ПК передбачено підключення декількох принтерів до одного комп’ютера. Порти їхнього підключення мають логічні імена LPT1, LPT2, LPT3. З погляду компілятора ВР імена PRN і LPT1 є синонімами. AUX - логічне ім’я каналу зв’язку нашого ПК з іншими машинами, які з’єднані з ним мережевим кабелем. У ПК є два комунікаційні пристрої з іменами СОМІ і COM2 - послідовні порти. Зазначимо, що AUXі СОМІ є синонімами. NUL - логічне ім’я так званого “порожнього” пристрою. На цей пристрій можна лише писати, проте читати з нього неможливо. Його використовують для перевірки поверхні диска на “читабельність”.
316 4.8. Файли 4.8.9. Процедури та функції загального призначення Робота з каталогами Опишемо робочу змінну: Var Name і String;. ChDir (' D: V ); {Встановити кореневий каталог диска D поточним}. ChDir (' С: \Temp'); {Встановити каталог С: \Тешр поточним}. GetDir ( 0, Name ); {Записати у змінну Name ім’я поточного диска і каталога}. Примітки: 1.Якщо зазначити ім’я неіснуючого диска, то на етапі виконання буде видане повідомлення про помилку: Error 15: Invalid, drive number. 2. Якщо вказати ім’я неіснуючого каталогу - отримаємо повідомлення: Error 3: Path not found. MKDir (<повне ім'я каталогу>); {Створити каталог на зазначеному диску}. Наприклад: MKDir (' С: \Rob' ); {Створення на диску С каталогу Rob}. MKDir ('С;\Temp\Robf); {Створення в каталозі C:\Tenp підкаталогу Rob}. RMDir (<повне імг я каталогу>); {Знищиш порожній каталог на зазначеному диску}. Примітка: Якщо зазначити ім’я непорожнього каталогу, то на етапі виконання отримаємо повідомлення про помилку: Error 5: File access denied. Робота з файлами Створити файл можна процедурою Rewrite, як це описано вище. Перейменувати файл можна так:
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 317 J Assign (F, ' OldName. dat') ; {Ініціювання файла}. Rename (F, f NewName.dat') ; {Перейменування файла}. Знищення файла з логічним іменем F здійснює процедура: Erase (F); . Робота з характеристиками файлів, каталогів, дисків Файлова система ПК містить, а також дає змогу отримати чи змінити певні характеристики та атрибути файла, каталогу та диска. Розглянемо стандартні процедури та функції мови ВР, які часто вживають з цією метою: GetFTime ( сім'я Ф3>, <змінна для результату>); . Повертає damy і час останнього запису у файл. <змінна для результату> є типу Longlnt. Після виконання процедури результат записується у внутрішньому запакованому вигляді. Щоб розпакувати його для друку, необхідно скористатись стандартною процедурою: UnPackTime (<змінна для результату>, Dt); Другий параметр процедури, який ми назвали Dt, необхідно описати так: Var Dt : TdateTime;. Тип TdateTime є вбудованим типом модуля winCrt такої структури: TdateTime = Record Year, Month, Day, Hour, Min, Sec: Word; End; . Програма для виведення на екран часу створення текстового файла: Program Demo_File_Date; Uses Crt, WinDos; Var f : Text; { опис текстового файла } ftime : Longint; { змінна для результату } Dt : TDateTime; { змінна типу Record для роботи UhpackTime } Function L__Zero (w : Word) : String; {Для форматування виведення результату } Var s : String;
318 4.8. Файли Begin Str (w:0, s); {Переведення з типу Word у тип String } If Length (s) = 1 then s := 'O' + s; { зліва дописує 0, якщо 1 символ} L_Zero := s; End; BEGIN ClrScr; Assign (f, 'TEST.TXT 1); Rewrite (f); {Створює новий файл} GetFTime (f, ftime); {Отримує час його створення в запакованому вигляді} UhpackTime (ftime, Dt); { Розпаковує отриманий час у змінну Dt} With Dt do Begin {Виведення на екран часу створення файла у форматі год:хв:сек} Writeln (’File stvoreno: L_Zero(hour) , L_Zero(min), ':1, L_Zero(sec)); End; Close (f); { закриває файл } Repeat Until KeyPressed END. З метою встановлення атрибута “час створенння файла”, значення, годин, хвилин і секунд часу спочатку необхідно записати у відповідні поля запису Dt (див. вище) і запакувати у спеціальний формат процедурою: % PackTime (Dt, <змінна для розміщення запакованого часу?>)/ Потім присвоїти встановлений час відповідному атрибуту файла процедурою: SetFTime{<Ф3>,<змінна для розміщення запакованого часу>); . Нижче наведено фрагмент програми, який встановить атрибут “час створенння” файла з логічним ім’ям F. Dt.hour := 2; {заповнення поля “години”} Dt.min := 12; {заповнення поля “хвилини”} Dt. sec : = 10; {заповнення поля “секунди”} PackTime (Dt, ftime) ;
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 319 SetFTime (F, ftime) ; Процедура: j GetFAttr ( F, Attr) ; записує атрибути файла у змінну типу Word. У модулі WinDos атрибути файла володіють такими назвами з відповідними шістнадцятковими значеннями: f aReadOnly $01 - тільки читання; faHidden $02 - прихований файл; faSysFile $04 - системний файл; f aVolumelD $08 - ідентифікатор дискового тому; faDirectory $10 - каталог; f aArchive $20 - архівний файл; faAnyFile $3F - будь-який файл. Комбінуючи ці атрибути як суми шістнадцяткових значень, можна задавати різні набори атрибутів. Наприклад: $02 + $04 = $06. Файл із таким значенням атрибута буде водночас прихованим і системним. Процедура: SetFAttr (F , Attr); встановлює атрибути файла за значеннями, попередньо записаними у змінну Attr типу Word. Функція: DiskFree (0) записує у змінну типу Longlnt число вільних байт поточного диска. Наприклад: Наступний фрагмент програми запише у змінну N розмір у байтах вільного простору поточного диска. Var N :Longlnt; BEGIN N := DiskFree (0) ; . Функція: ГізІгЗІге (0) записує у змінну типу Ьо^Іпї значення усього об’єму поточного диска у байтах.
320 4.8. Файли 4.8.10. Робота з файлами різних типів Типізовані, нетипізовані і текстові файли використовують у PascaZ-програмах за різними правилами. Типізовані файли У типізованому файлі усі компоненти є однотипними: мають однакову довжину і внутрішній формат запису даних. Елементи файла автоматично нумеруються, починаючи з нуля. Наявність нумерації дає змогу застосовувати до його елементів як послідовний, так і прямий спосіб доступу. Операції читання з типізованого файла можна робити тільки процедурою Read, а запис - тільки процедурою Write. У цьому випадку змінні, що беруть участь в операціях читання/запису (тобто параметри процедур Read і Write) повинні бути однотипними з компонентами файла. Після читання кожного наступного елемента файла, за послідовного доступу, значення файлового вказівника зростає на 1. У випадку спроби прочитати елемент, який виходить за межі файла, одержимо повідомлення про помилку. Для організації прямого доступу до компонентів файла середовище ВР містить такі процедури і функції: Процедура: % Seek ( сім'я Ф3>, сномер компоненти> );\ переміщає вказівник відкритого файла на компоненту, номер якої задає її другий параметр - змінна або вираз типу Longlnt. Щодо текстових файлів цю процедуру застосовувати заборонено. Процедура: Truncate ( сім'я Ф3> ); знищує всі елементи відкритого файла, які знаходяться після поточної позиції вказівника файла. Функція типу Longlnt: FilePos ( сім'я Ф3> )
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 321 повертає номер поточної позиції вказівника файла. Якщо пказівник поточної позиції файла розташований на початку файла, то FilePos (F) повертає нуль. Якщо вказівник розташований наприкінці файла, то значення FilePos (F) дорівнює значенню поточної кількості елементів файла, якщо їх нумерувати від одиниці. Це значення також повертає функція: FileSize ( <ім'я Ф3> ); Обидві функції не можна використовувати для текстових файлів. Файл повинен бути відкритим. Нетипізовані файли Нетипізовані файли найчастіше використовують для швидкісного обміну даними між диском і пам’яттю. Вони дають змогу працювати з файлами будь-якого типу і логічної структури, здіснюючи операції читання/запису великими блоками. Величину блока можна зазначити у процедурі Reset або Rewrite таким способом: Reset (F, <довжина блока> ); або Rewrite (F, <довжина блока> )/. Якщо довжину блока явно не зазначити, її вважатимуть рівною 128. Можна зазначити максимальну довжину блока як 65535 байт, проте максимальна швидкодія досягається за довжини 512 байт, яка дорівнює розміру фізичного сектора диска. Під час роботи з нетипізованими файлами можна використовувати усі стандартні процедури і функції, що ми описували для файлів типізованих, за винятком процедур читання/запису Read і Write. Роль таких процедур у цьому випадку виконують процедури читання/запису однієї або більше порцій даних між файлом і змінною: BlockRead ( F, Buf, Count [, Result ]); BlockWrite{ F, Buf, Count [, Result ]); , де: 11 7-451
322 4.8. Файли • F файлова змінна, описана як нетипізований файл; • Buf будь-яка змінна; • Count вираз типу Word; • Result змінна типу Word - необов’язковий параметр. Принцип роботи цих прбцедур: Процедура BlockRead прочитує Count або менше блоків з файла F в область пам’яті, яка починається з першого байта області, зайнятої змінною Buf. Справжня кількість прочитаних блоків, що є меншою або дорівнює Count, повертається в необов’язковому параметрі Result. Якщо параметр Result не визначено, то за умови, що кількість прочитаних блоків не дорівнює значенню параметра Count, одержимо повідомлення про помилку. Увесь прочитаний блок займає максимум Count*RecSize байт, де RecSize - розмір блока, зазначений при відкриванні файла (128 байт, якщо розмір блока не зазначено). Якщо Count*RecS±ze перевищує 64Кб, одержимо повідомлення про помилку. Параметр Result не є обов’язковим. Якщо всю задану порцію даних зчитано, то Result становитиме Count. Якщо ж значення Result менше, ніж Count, то кінець файла досягнуто раніше, ніж завершено читання блока. Якщо параметр RecSize становитиме понад /, то Result поверне кількість цілковито прочитаних блоків. Вказівник поточної позиції файла переміща-ється на кількість блоків, що дорівнює значенню параметра Result. Усе зазначене є справедливим, якщо на момент читання файл було відкрито. Процедура BlockWrite записує один або більше блоків зі змінної у файл. Зміст її параметрів такий, як у процедури BlockRead. BlockWrite записує Count або меншу кількість блоків у файл F з області пам’яті, що починається з першого байта, зайнятого змінною Buf. Справжня кількість записаних елементів (менша або дорівнює Count) повертається в необов’язковому параметрі Result. Якщо параметр Result не визначено, якщо кількість прочитаних записів не дорівнює параметрові Count, одержимо повідомлення про помилку. Уся записана порція займає максимум Count*RecSize байт, де RecSize - розмір блока, зазначений під час відкривання файла
4. ВІЗУАШЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 323 (128 байт, якщо розмір блока не зазначено). Якщо Count*RecSize перевищує 64Кб, буде видане повідомлення про помилку/ Параметр Result є необов’язковим. Якщо усі зазначені дані записано, то Result становитиме cfount. Якщо значення Result менше ніж Count, диск переповнився до завершення запису блока. Якщо ж параметр RecSize становить понад 7, Result поверне кількість цілком записаних елементів. Вказівник поточної позиції файла переміщається на кількість блоків, що дорівнює значенню параметра Result. Файл на момент запису має бути відкритим. Текстові файли Структура текстових файлів відрізняється від структури звичайних файлів (лінійної послідовності елементів одного типу) тим, що вміст текстового файла складається з набору рядків змінної довжини, розділених спеціальною комбінацією кодів “кінець рядка”. Ця комбінація формується з управляючого коду “переведення каретки” (CR, Carriage Return, символ #13), за яким розташовано управляючий код “переведення рядка” (LF, Line Feed, символ #10). Ознакою формування кінця рядка вважають натис¬ нення клавіші |E/ifer«4 Послідовність кодів #13# 10 наприкінці кожного рядка текстового файла має спеціальну назву eoln (End LiNe - кінець рядка). Текстовий файл завершується спеціальним кодом “кінець файла” (eof (end virtual - кінець файла, символ #26)). Зазначимо, що, здебільшого, знання конкретного кодування управляючих символів не є обов’язковим, оскільки файлові процедури ці символи проставляють автоматично. Середовище ВР містить стандартні функції, які повертають значення названих керуючих символів. Структуру текстового файла схематично можна подати як набір рядків символів різної довжини. Змінна довжина компонентів текстового файла істотно впливає на характер роботи з ними. Доступ до кожного рядка можливий лише послідовно, починаючи з першого. Переваги текстових файлів • простота створення (можливість безпосереднього набору даних на клавіатурі);
324 4.8. Файли • наочність (візуальний перегляд вмісту файла засобами текстових редакторів); • універсальність (у багатьох задачах можна обійтися тільки цим видом файлів). Особливості текстових файлів • Для одного текстового файла неможливо водночас здійснювати операції і введення, і виведення. Це означає, що після відкривання текстового файла процедурою Reset можливе тільки читання інформації з файла, а після процедури Rewrite - тільки запис у файл. • Обміни з текстовими файлами завжди є тільки послідовними, тобто після читання з файла елемента з порядковим номером N наступна операція читання дасть елемент з номером TV+І. Іншими словами, прямий доступ до будь-якого елемента текстового файла є неможливим. • Щодо текстових файлів не можна застосовувати процедури Seek, FilePos, FileSize. • Базовою технікою обмінів з текстовими файлами є посимвольне введення-виведення. Щодо цього відбувається читання або запис усіх символів - як інформаційних, так і спеціальних. • Ще однією особливістю роботи з текстовими файлами є можливість безпосередніх обмінів значеннями різних базових типів (для звичайних типованих файлів, тип параметрів у процедурах Read і Write повинен збігатися з базовим типом файла). У текстовий файл можна записати, наприклад, ціле або дійсне число. У цьому випадку його внутрішнє представлення буде автоматично перетворено в рядок символів, що відповідають зображенню цього числа. Основні оператори для роботи з текстовими файлами Нагадаємо, що файлову змінну текстового файла описують так: Var F : Text; .
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 325 Операції читання з файла: Процедура: Reset (F)/ відкриває існуючий файл для читання. Треба передбачити взаємозв’язок файлової змінної із зовнішнім файлом за посередністю процедури Assign. Якщо існуючий файл уже відкрито, його закривають, а потім відкривають знову. Вказівник файла автоматично розташовується на початку файла. Якщо файлову змінну F пов’язати з порожнім іменем (інаприклад, Assign (F, 1 1) ;, то після виконання процедури Reset (F); відбуватиметься посилання на стандартний файл введення (канал з номером 0). За наявності директиви компілятора {$1-} функція без параметрів lOResult повертатиме 0 у тому випадку, якщо операція завершилася успішно, і ненульовий код помилки в іншому випадку. Процедура: Read (F, ссписок введення>); прочитує з файла одне чи більше значень в одну або більше змінних. Процедура: Readln (F, vl, v2,....,vn); виконує процедуру Read, потім переходить до наступного рядка файла. Якщо в рядку залишилися дані, що не увійшли до списку введення, вони ігноруються. Процедура Readln є розширенням процедури Read, її призначено для текстових файлів. Виклик Readln (F); без параметрів спричинює переміщення поточної позиції файла на початок наступного рядка, якщо він існує. В протилежному випадку відбувається перехід до кінця файла. Процедура Readln є зручним аналогом Read. У разі використання Readln після чигання з файла чергової порції символів (і перетворення їх у значення відповідного типу) поточний покажчик файла буде переміщено на початок його наступного рядка. Іншими словами, частину рядка після прочитаного значення буде пропущено. Використовують і такий спосіб читання з текстового файла. Якщо параметром процедури Readln слугує змінна типу string, в цьому випадку весь черговий рядок файла цілком прочитується в
326 4.8. Файли подану змінну, довжина якої автоматично встановлюється рівною довжині рядка, що читався. Отриманий з файла рядок далі може оброблятись за алгоритмом нашої програми. Зауважимо, що за такого способу відбувається читання тільки “значущих символів” рядка. Символи, що завершують рядок, в рядкову змінну не прочитуються. Після читання рядка вказівник файла встановлюється на початок наступного рядка. Операції запису у файл: Процедура: Rewrite (F) ; створює і відкриває новий файл. Необхідно передбачити взаємозв’язок файлової змінної із зовнішнім файлом за посередністю процедури Assign. Якщо зовнішній файл вже існує, то він знищується і на його місці створюється новий порожній файл. Якщо файл уже відкрито, його закривають, а потім відкривають знову. Вказівник встановлюється на початок файла. Якщо F було пов’язано з порожнім ім’ям (,наприклад, Assign (F, 1 1 ) ;, то після звернення до Процедури Rewrite (F) ; буде посиланням на стандартний файл виведення (канал 1). Текстовий файл стає доступним тільки для запису. Процедура: Write (F, [vl, v2, ...., vn]); записує одне чи більше значень з однієї або більше змінних у текстовий файл. Якщо параметр F не зазначено, то за замовчуванням використовується стандартна файлова змінна Output. Кожен параметр v є виразом, значення якого необхідно записати у файл виведення. Кожен вираз, що вводиться, повинен бути символьного, цілого, дійсного, рядкового або булевого типу. Параметр v може набувати вигляду: <вираз>:<кількість символів>:Скількість символів у дробовій частині>. Наприклад: Var R : Real; Write (F, R:5:2); . Такий запис означає, що ми у файл записуємо дійсне число R, розміром 5 знаків, з яких 2 знаки відведено під дробову частину.
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 327 Процедура: Writeln (F, [vl, ч2, ...., уп]); виконує процедуру Write, а потім записує у файл позначку кінця рядка (переведення рядка). За виклику процедури Writeln (F) ; без параметрів, у файл записується мітка кінця рядка. Примітка: файл повинен бути відкритим для виведення. Логічну функцію: Eoln (F) використовують для обробки текстових файлів. Вона дає змогу визначити, чи досягнуто кінця рядка. Якщо досягнуто - значення функції становитиме True, а якщо ні - False. Наприклад, для аналізу символів рядків файла можна застосувати вкладений цикл: While not Eoln (F) do {виконуй, поки немає кінця рядка файла F} Begin {група операторів обробки символів чергового рядка} End; Логічна функція: Eof (F) дає змогу визначити, чи досягнуто кінця файла. Якщо досягнуто - значення функції становитиме True, а якщо ні - False. Наприклад, для пошуку позначки закінчення файла використовують цикл: While not Eof (F) do {виконуй, поки немає кінця файла F} Процедура: Арреї^ {¥) ; відкриває існуючий файл для його доповнення. Якщо файл вже відкрито, його спочатку закривають, а потім відкривають наново. Поточну позицію вказівника встановлюють наприкінці файла. Якщо в останньому блоці файла розміром 128 байтів присутній С/г/+2 (26 в коді АБСТІ), то поточна позиція символ встановлюється у файлі так, що під час запису першим у блоці “затиратиметься” символ С/г/+2.
328 4.8. Файли Якщо змінній F присвоєно порожнє ім’я процедурою Assign (F, ' то звернення до процедури Append (F) ; указуватиме на стандартний вихідний файл. Після звернення до процедури Append (F); файл F стає доступним тільки для запису і Eof (F) завжди набуває значення True. Окрім перелічених вище процедур і функцій для роботи з файлами, інколи доцільно використовувати процедури (функції), які наведено у таблиці 4.13. Таблиця 4.13 Додаткові процедури для роботи з текстовими файлами Процедура (функція) \ Дія SetTextBuf (F, { буфер [,розмір]) І ... —1 Призначає буфер уведення-виведення для файла (за замовчуванням розмір буфера -128 байт) Flash (f) I Виштовхує вміст буфера файла виведення SeekEoln (f) і Повертає ознаку кінця рядка, заздалегідь і оминаючи всі пропуски і символи табулювання | SeekEof (f) \ J Повертає ознаку завершення файла, заздалегідь оминаючи всі пропуски, символи табулювання і j ознаки закінчення рядка | Приклад. Дано масив цілих чисел, записаний в одновимірну таблицю з індексами, що змінюються від 1 до 100. У таблицю М у порядку зростання записати тількі ті числа, залишок від ділення яких на 3 дорівнює 1, а залишок від ділення на 5 - дорівнює 2. Кількість таких чисел запам’ятати у К. Подамо алгоритм написання програми, яка розв’яже цю задачу. 1. Описуємо два масиви цілих чисел А і АГ заданого в умові задачі розміру. 2. Описуємо чотири змінних цілого типу: *,/’, к, і?. 3. Генератором випадкових цілих чисел заповнюємо значеннями масив А. 4. Відбираємо з масиву А компоненти, які задовольняють умову задачі і записуємо їх у масив М, 5. Перевіряємо, чи масив М не є порожнім, і чи не містить він лише один елемент. Якщо так, то видаєм
4. ВІЗУАЛІЗАЦІЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ 329 відповідне повідомлення на екран і зупиняємо^ виконання програми. 6. Якщо ні, то сортуємо масив у порядку зростання. 7. Виводимо на екран* елементи масиву М і їхню кількість. 8. Завершуємо роботу програми. Program XIO_Massyv; Uses Crt; Var A, M : Array [1..200] of Integer; i, j, k, r : Integer; Ft : Text; L : Boolean; BEGIN ClrScr; Assign ( Ft , 1 Rob.dat1 ); Rewrite ( Ft ); {Заповнення масиву А різними випадковими цілими числами } Randomize; А [1] : = Random (500); і : = 2; Repeat L := True; R := Random (500); For j:= 1 to і - 1 do If A [j] = r then L := False; If L then Begin A [i] := r; і := і + 1; End; Until і = 201; {Заповнення масиву M числами, що задовольняють умову задачі} К := 0; For і:=1 to 200 do Begin If (A [і] mod 3 = 1) and ( A [i] mod 5 = 3) then Begin k := k + 1; M [k] := A [i] End End;
330 4.8. Файли {Упорядкування масиву М у порядку зростання} For j:= 1 to k - 1 do Begin і := 1; While і <= k - j do Begin If M [і] > M [i + 1] then Begin R := M [i]; M [і] := M [i + 1]; M [i + 1] := r End; і := і + 1 End End; If k = 0 then Begin Writeln (’ масив M - порожній1); Writeln (' k=f , k); Repeat Until KeyPressed; Halt End; Writeln (T k=' , k); {Запис масиву M у текстовий файл} For і:=1 to k do Writeln (Ft, m[i]); Close (Ft) END.
5. ЗВ'ЯЗОК PASCAL - АСЕМБЛЕР “Засоби, які ми застосовуємо, роблять глибокий (і тонкий) вплив на наші способи мислення і, отже, на нашу 'здатність мислити”. Едсгер Дейксмра “Я думаю, що деякі з найсерйозніших помилок, які люди здійснюють на верхніх рівнях архітектури, зумовлені неповним або неправильним розумінням певних простих речей самого низького рівня. Ви побудували прекрасиий палац, але трішки помилились десь у районі фундаменту. Замість бетонних блоків там виявилось якесь сміття. Палац виглядає чудово, тільки ванна іноді відхиляється вбік, і не зрозуміло, чому”. Джоель Спольский - засновник FogCreek Software, невеликої нью-йоркської компанії з розробки програмного забезпечення. Сьогодні у розробці програмного забезпечення спостерігаються дві протилежні тенденції. Перша - розробити величезний програмний комплекс у короткий час, використовуючи найсучасніші технології. Друга - створити програму, яка якнайповніше, враховуючи всі особливості конкретного апаратного забезпечення, розв’язуватиме певний клас задач із максимальною швидкістю, затрачаючи при цьому мінімум ресурсів комп'ютера. У першому випадку застосовують найновіші об'єктно-орієнтовані та візуальні технології. Інструментом для другого випадку є Асемблер. Асемблер (Assembler) - машинно-орієнтований засіб програмування низького рівня. В перекладі з англійської слово assembly означає збирання, монтування. Написана на Асемблері програма є послідовністю команд конкретного процесора, закодованих в
332 5.1. Що таке Асемблер? умовній мнемонічній формі. Саме машинна орієнтація визначає преваги і недоліки Асемблера. У 50-ті роки XX століття винахід Асемблера вважали першим і дуже важливим кроком на шляху автоматизування процесу програмування. Він позбавляв програмістів необхідності записувати тексти програм у послідовності вісімкових чи шістнад- цяткових рядків. Адже для позначення команд процесора, їхніх операндів і адрес даних замість чисел почали використовувати імена і спеціальні символи. Окрім того, транслятори, а згодом і компілятори давали змогу застосовувати спеціальні директиви для опису змінних, оформлення макроозначень і сегментації програм. Усе це істотно спрощувало та прискорювало повсякденну роботу програміста. З розробкою перших мов програмування високого рівня, передусім оптимізуючих компіляторів для них, в середовищі програмістів поширилась впевненість у тому, що програмування на Асемблері є неперспективним. Мови високого рівня вимагали від програміста меншої спеціальної підготовки, а їхня машинна незалежність давала змогу організувати обмін алгоритмами, програмами і здійснити їхню публікацію у пресі. Головним аргументом на підтвердження цього була значно вища складність розробки програм на Асемблері. Дослідження засвідчили, що кількість рядків програми, яку програміст пише і налагоджує за певний проміжок часу, не залежить від мови програмування. На прикладі використання мови Рогігап для розв’язування науково- технічних задач встановлено, що в середньому асемблерна програма є у три-чотири рази довшою, ніж фортранівська. Подальший розвиток техніки компілювання мов високого рівня, таких як мова О, спричинив до ілюзії, що без Асемблера можна цілком обійтись. З розвитком персональної комп’ютеризації Асемблер на деякий час знову опинився серед лідерів: обмежені можливості перших моделей ПК не передбачали застосування компіляторів з мов високого рівня. Однак технічний прогрес поступово усунув ці недоліки, і програмісти знову віддавали перевагу алгоритмічним мовам. Вважалось, що на Асемблері пишуть тільки драйвери і віруси. Отож, фахівцям, здебільшого, Асемблер не потрібен. На нашу думку, таких поглядів дотримуються програмісти, у яких недостатньо практичних навичок унаслідок обмеженості їхніх
5. ЗВ’ЯЗОК PASCAL-ЛСЕМБЛЕР 333 професійних знань. Безперечно, з погляду складності і трудомісткості процесу програмування, Асемблер поступається алгоритмічним мовам, однак це не означає, що його не варто знати й уміти застосовувати за необхідності. Оскільки універсальної мови програмування на всі випадки життя досі не існує, та й потреба у ній не надто очевидна, з метою розширення сфери діяльйоеті^і підвищення професійного рівня програміст повинен володіти декількома мовами та засобами програмування. Бажано, щоб серед них був Асемблер. Практика програмування внесла свої корективи. Сьогодні достатньо поглянути на полиці книжкових крамниць і серед різноманітних видань можна помітити кілька нових солідних книг із категоричними назвами типу: “Асемблер - мова необмежених можливостей”. Навіть побіжний перегляд Internet-сайтів на комп’ютерну тематику засвідчує, що Асемблер застосовують і зацікавлення ним так швидко не мине [39, 90]. Кожна мова високого рівня, у тому числі і Borland Pascal, дає змогу програмістові вставляти у текст своєї програми фрагменти на Асемблері. Отож, цей розділ присвятимо короткому описові елементів програмування на Асемблері та розглядові питань щодо поєднання Асемблера і мови Pascal. 5.1. Що таке Асемблер? Ми вже згадували, що Асемблер, з одного боку, - це набір команд відповідного мікропроцесора, які записують за певними правилами у мнемонічній формі, зручній для сприйняття людиною, а з іншого боку - це програма, яка переводить нашу асемблерну програму у двійковий машинний код, зрозумілий процесору. Безперечно, перевагою Асемблера є можливість, під час створення програм, раціонально використовувати всі особливості системи команд конкретної ЕОМ. Він надає необмежені можливості для різноманітних трюків (у доброму значенні цього слова), тут все залежить від професійних навичок програміста і його винахідливості. Саме Асемблер дає змогу перетворити процес створення програми з ремесла у мистецтво, тому його шанує і використовує так мало фахівців. Адже справжніх віртуозів програмування є одиниці.
334 5.1. Що таке Асемблер? Іншою позитивною властивістю слугує універсальність Асемблера як засобу програмування. Він дає змогу скласти програму для будь-якої задачі, яка має рішення і може бути розв’язана на машинах цього типу. Адже будь-яка програма, складена на мові високого рівня, при компілюванні перетворюється у послідовність машинних команд. Очевидним недоліком Асемблера є низький рівень абстрагування від особливостей конкретної ЕОМ, необхідність знати і враховувати ці особливості. Під час роботи із мовами високого рівня програміст може цілковито зосередити свою увагу на особливостях алгоритму, який необхідно запрограмувати. Іншим недоліком є надто велика кількість команд та їхніх модифікацій, що підтримуються сучасними мікропроцесорами. Наприклад, у мікропроцесора Репйит 4 їх близько 500! Це змушує користуватися при роботі спеціальними довідниками, оскільки важко втримати в голові усю різноманітність імен команд і особливостей їхнього виконання. Хоча все залежить від досвіду та інтелекту конкретного програміста. Оскільки Асемблер є набором команд певного процесора, то це означає, що програму, написану на Асемблері для /несумісного процесора, доведеться цілковито переписувати для МасШозк і не потрібно переписувати для МП фірми АМВ, оскільки вони є сумісні з платформою МП фірми ІМеІ. У такому зв’язку з головною обчислювальною мікросхемою комп’ютера прихована вся потужність і слабкість програм на Асемблері, з одного боку, всі можливості процесора використовуються максимально, з іншого - перенести такі програми на іншу платформу є надто важко. Саме тому у мовах високого рівня передбачено можливість вставки фрагментів коду на Асемблері. На ньому можна реалізувати невелику, але важливу, з погляду використання машинних ресурсів, частину коду, а все інше писати на улюбленому С++ або Разсаі. У цьому випадку програми і писатимуться, і працюватимуть швидше, та і під іншу платформу, за необхідності, їх перенести значно легше. Виникає закономірне запитання: які частини алгоритму бажано реалізувати на Асемблері? Автори багатьох книг з Асемблера починають свої праці з наступної інформації: у будь-якому складному програмному продукті можна виокремити 10% коду, які під час роботи програми
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 335 займають 90% процесорного часу. Можна навести будь-яку популярну гру: її ядро або частково, або цілковито написано на Асемблері. Наприклад, в грі Unreal близько 40% всього коду створено саме так. Інший приклад - вірус. Йому необхідноЧ^ед^-файл неза- ражений відшукати, і заразити його, і стерти що-небудь важливе, і пароль вкрасти та своєму творцю його на e-mail надіслати. Причому зробити все це так швидко, щоб користувач не помітив. Тут альтернативи немає - тільки Асемблер. Найгостріше це відчувається у програмах, які роблять будь- які достатньо складні математичні обчислення. Якби їхнє ядро писали не на Асемблері, то чекати результату довелося б у 2-3 рази довше. Дослідження, виконані автором цих рядків на прикладі розв’язання високого порядку систем лінійних алгебричних рівнянь методом Гауса, засвідчили, що у цьому випадку процес пришвидшується у 3-10 разів, залежно від розміру системи, яку розв’язують. Програми на Асемблері виходять, здебільшого, значно меншими за своїх побратимів, створених на мовах високого рівня. Досягається це, як вже згадувалося вище, завдяки прямій взаємодії з процесором, і, як наслідок, - з ОС. Навіть у разі введення фрагментів Асемблера у програми на мовах високого рівня різницю легко помітити. Втім, чинник розміру був актуальнішим за часів п’ятидюймових дискет і десятимегабайтних вінчестерів. Сьогодні, коли майже ніхто не бачить особливої різниці (гігабайтом більше або менше - подумаєш!), про економію у двадцять-тридцять кілобайтів говорити якось незручно. Втім, зменшення розміру можна вважати приємним бонусом до підвищення швидкодії. І останнє. Якщо необхідно просто вивести на екран якийсь рядок або обчислити корені рівняння - достатньо і Бейсіка. Розробку складнішої програми, при реалізації якої необхідно використовувати перевантаження операторів, об’єкти і т. п., ліпше всього здійснювати на C++. А якщо, окрім всього іншого, необхідно, наприклад, працювати напряму з портами уведення- виведення або робити складні обчислення з плаваючою комою? Тут без Асемблера не обійтись. У будь-якому випадку, спрацьовує правило: необхідно щось написати - пиши на мові Pascal, Fortran чи C++. Не виходить на цих мовах - пиши на Асемблері. Якщо і на ньому не виходить - цього взагалі не можна зробити.
336 5.2. Асемблер і Макроасемблер 5.2. Асемблер і Макроасемблер З погляду програміста “чистий” Асемблер є підмножиною Макроасемблера. Останній, поряд із компілюванням повного набору команд конкретної сім’ї мікропроцесорів, ще виконує чимало операторів і директив (далі макрозасобів) різного призначення. У програмістів, що працюють на комп’ютерах IBM PC, найбільшою популярністю користуються макроасемблери MASM фірми Microsoft і - TASM фірми Borland. Вони володіють приблизно однаковими можливостями і багато в чому (але не цілком) сумісні. Зазначимо, що в чистому вигляді Асемблер застосовують тільки при оформленні вставок у тексти програм, що складаються на мовах високого рівня. Без використання макрозасобів важко скласти навіть просту підпрограму, не кажучи про завершені програми. За певних умов початковий текст програми, що виконує достатньо складні дії, може містити тільки макрозасоби. В ньому не буде жодної команди Асемблера! Про яку складність і трудомісткість програмування можна говорити в подібних випадках? У документації з MASM, у тім числі і в HELP, зазвичай, описують 8 типів операторів і 12 типів директив, які належать до макрозасобів. Починаючи з версії MASM 6.10, їхня кількість не змінювалася. Обмежимося загальною характеристикою макрозасобів. Директиви макроасемблера призначені для виконання трьох головних категорій дій: • управління розподілом ОП. Виконують директиви, Призначені для опису простих змінних, структур даних, записів і сегментації програм; • управління роботою із зовнішніми і внутрішніми підпрограмами, фрагментами програм і макро- означеннями. Виконують директиви їхнього явного або попереднього опису і виклику; • управління процесом компілювання програми. Виконують директиви умовного компілювання, серед них трапляються такі знайомі кожному програмісту імена, як If, else, For, While, Repeat, GOTO.
5. ЗВ ЯЗОК PASCAL-ACEMKriEP 337 Незалежно від конкретного призначення, всі директиви та оператори виконуються на стадії компілювання, у цьому випадку самі вони не перетворяться в команди. Унаслідок їхнього виконання в об’єктний модуль записуються або не записуються групи команд, розташовані в початковому тексті програми або в зовнішніх бібліотеках. Окрім того, в об’єктний модуль надходять дані, необхідні компонувальнику (/лліАеру) для формування і побудови програми. Отже, при обговоренні достоїнств і недоліків програмування на Асемблері необхідно пам’ятати, що на практиці ми, зазвичай, працюємо з мовою Макроасемблера, а це далеко не одне і те саме. 5.3. Техніка програмування Ахілесовою п’ятою Асемблера є трудомісткість програмування на ньому. Що може зробити програміст для полегшення власної праці? Єдиним можливим рішенням проблеми є накопичення і використання власного та чужого досвіду, оформленого у формі бібліотек або окремих модулів, бажано з критичною оцінкою цього досвіду. Макроасемблер дає змогу застосовувати, під час розробки задачі готові вихідні та об’єктні модулі. Перші вводять у початковий текст програми за допомогою директиви Include, а другі долучаються до списку об’єктних модулів на стадії побудови задачі компонувальником. Існують різні джерела об’єктних і вихідних модулів, одні з них дещо доступніші, а інші - менше. Вибір залежить від наших можливостей. До повноцінної версії системи програмування на Макроасемблері (дистрибутивного пакета) входить набір макроозначень і підпрограм різного призначення та приклади їхнього використання. Уважно передивіться усі підкаталоги Вашої версії Макроасемблера. Ймовірно, Ви відшукаєте чимало корисних та цікавих рішень, які можна використати у роботі. Не забувайте про те, що під час складання програм можна використовувати модулі бібліотек, які належать до систем програмування мовами високого рівня, наприклад, Сі. Щоправда, Вам необхідно мати опис цих бібліотек, адже без нього неможливе
338 5.3. Техніка програмування їхнє використання і в межах тієї системи програмування, для якої їх створено. Якщо у Вас є доступ до мережі Internet, то на різних її сайтах можна відшукати безліч готових рішень буквально на всі випадки життя. Тільки звертайте увагу на дати розробки програм і підпрограм. Багато з них морально застаріли. Шляхом застосування нових команд мікропроцесорів їх можна істотно спростити. Під час роботи з Асемблером у Вас поступово накопичуватиметься набір власних рішень, які стануть у пригоді в нових розробках. Для зручності їхнього подальшого використання намагайтеся під час написання програм складати якомога більше підпрограм, оформлених як окремі модулі, ліпше початкові, а не об’єктні. Перші, за необхідності, простіше модифікувати. Застосування підпрограм дещо збільшує розміри задачі та уповільнює процес її виконання. Проте, у результаті, Ви матимете змогу налагоджувати велику програму частинами і використовувати готові підпрограми у подальших розробках. Не забувайте про існування такого ефективного засобу, як макроси - макроозначення і макровиклики. Вони дають змогу скорочувати не тільки початковий текст програми, але й кількість можливих помилок під час його набору. Окрім цього, макровиклики зручно застосовувати при запиті системних функцій, які виконують чимало корисних дій, таких як робота з вікнами, з файловою системою, введення/виведення даних та ін. Отже, за наявності досвіду і практичних навичок, витрати праці під час програмування на Асемблері можна звести до такого рівня, який передбачатиме розробку достатньо великих проектів. Безумовно, перед їхньою реалізацією необхідно зважити усі докази за і проти і врахувати свої реальні можливості. 5.4. Коли Асемблер без альтернативи? Традиційно Асемблер застосовують для написання підпрограм і вставок у програми, складені на алгоритмічних мовах. Останніми роками доцільність такого його застосування не тільки збільшилася, але й отримала нове значення. Адже задачі, які розв’язують програмами, розробленими на алгоритмічних мовах, украй неефективно використовують ресурси сучасних
5. ЗВ’ЯЗОК PASCAL-ЛСЕМБЛЕР 339 мікропроцесорів. Зрозуміло: це недоліки не мови, а компіляторів, які не підтримують роботу з груповими операціями і не враховують особливостей конвеєрної обробки. Усі намагання інженерів і проектувальників, спрямовані на підвищення продуктивності мікропроцесорів, виявляються даремними, як і наші фінансові витрати на придбання нового устаткування. Звинувачувати у цьому розробників компіляторів не варто. Проблема не така тривіальна і для її вирішеннянеобхідно не тільки покращувати техніку компілювання, але й розробляти принципово нові мовні засоби. Ми звикли до того, що арифметичні та логічні операції виконуються над однією парою операндів, іноді над одним операндом (зміна знака чи заперечення). А групові операції сучасних мікропроцесорів (не тільки сім’ї Pentium) можуть оперувати відразу з декількома парами операндів, кількість і розрядність яких не зафіксовано. У цій ситуації альтернативи Асемблеру просто не існує. Недарма у технічній документації до компілятора “Intel С++ Compiler” рекомендують три варіанти роботи з новими командами: • прямі вставки асемблерного тексту в тіло програми, написаної на Сі; • складання процедур (підпрограм) на Асемблері; • використання Intrinsic (вбудовані функції). Останні є альтернативною формою запису групових операцій і, насправді, не спрощують (швидше ускладнюють) задачу програміста. Окрім введення групових операцій, для підвищення продуктивності сучасних мікропроцесорів застосовують конвеєрну обробку інструкцій. З метою розширення її можливостей безперервно ускладнюють мікроархітектуру, що неминуче збільшує вартість виробів. Використовувати переваги конвеєрної обробки не так просто, як це може здаватись. При складанні програми будь-якою мовою ми виходимо з припущення про те, що машина спочатку виконує команди почергово, починаючи з першої. Насправді сучасні процесори вже давно так не працюють, вони намагаються цілковито або частково сумістити виконання декількох команд. Очевидно, що звичайні задачі не пристосовані для цього, і під час їхнього виконання продуктивність процесора не відповідає його реальним можливостям.
340 5.4. Коїш Асемблер без альтернативи Отож, у старої проблеми оптимізації з’явилися нові аспекти: необхідно виявляти і змінювати ті місця задачі, в яких продуктивність процесора занижено, бажано вилучити з програми або звести до мінімуму умовні галуження (наприклад, за результатом порівняння операндів) і т. д. Вирішити подібні проблеми в процесі компілювання програми, складеної на алгоритмічній мові, сьогодні не вдалося, і ми знову звертаємося до Асемблера. Компанія Intel розробила і продає спеціальний аналізатор продуктивності мікропроцесора в процесі виконання конкретної задачі (VTune™ Performance Analyzer 6.0). Він дає змогу виявити в ній слабкі місця (критичні ділянки коду задачі), і згодом виправити їх за допомогою асемблерних вставок. Докладніше щодо нових можливостей мікропроцесорів можна прочитати у статті [90]. Отож, в процесі роботи програмістові час від часу доводиться освоювати нові мови. При цьому він може переслідувати різну мету: від простого задоволення цікавості і розширення кругозору до суто практичних потреб типу розробки утиліт для вирішення задач новою мовою. Якщо Ви налаштовані розширювати свій кругозір, то ще раз прочитайте вислів Е. Дейкстри про вплив мови на спосіб мислення, який ми поставили епіграфом до цього розділу. Освоюючи тільки алгоритмічні мови, Ви, програмуючи, звикаєте думати формальними категоріями, заснованими на синтаксисі та семантиці. Це не погано, проте дещо однобоко. Врешті-решт, ми маємо справу не з віртуальною, а з реальною технікою і бажано уявляти, як вона працює. В цьому випадку Вам простіше зрозуміти, що можна і чого та чому не можна зробити за допомогою засобів тієї чи іншої алгоритмічної мови. Щоб залишатися на вістрі технічного прогресу й уміти створювати задачі, раціонально використовуючи можливості найсучасніших комп’ютерів, необхідно досконало володіти мистецтвом програмування ЕОМ. Оволодіти цим мистецтвом без знання Асемблера практично неможливо.
5. ЗВ’ЯЗОК РАБСАЬ-А СЕМБЛЕР 341 5.5. Робота в Асемблері Наше завдання - опанувати основи програмування на Асемблері з метою заміни критичних, з погляду швидкодії, фрагментів Ро«са/-програм їхніми аналогами на Асемблері, а також виконання функцій, які мовою ВР не програмуються, наприклад, під’єднання до програми “миші” або запуск графічного режиму 5К(Ї4. На наш погляд, команди Асемблера доцільніше вивчати автономно під управлінням Таьпиехе або МатСехе^ Розробка автономної програми на Асемблері налічує такі ёТапи: • Розробка алгоритму розв’язання поставленої задачі. • Написання програми згідно з правилами Асемблера. • Введення, за допомогою будь-якого текстового редактора (наприклад, редактора середовища ВР), тексту програми і запис її на диск у файл під деяким іменем, наприклад, Му_Рго]>г.а$т. Ім’я файла може бути будь- яким, а розширення аБт - обов’язкове. • Переклад (іасемблювання) вихідної програми в машинні коди за допомогою Тоэпиехе. Результатом цього етапу буде проміжний двійковий файл Му_Рго^.оЦ (об’єктний код). У випадку наявності у програмі синтаксичних та орфографічних помилок їх можна проаналізувати у текстовому файлі My_Progr.lst. Файл Му_Рго^.оЩ буде створено тільки тоді, коли всі помилки буде усунено. • Перетворення (лінкування) за допомогою програми Т1іпк.ехе об’єктного коду Му_Рго^.оЬ] у виконуваний файл My_Progr.exe або My_Progr.com. • Виконання програми в середовищі налагоджувана Т&ехе з метою пошуку та виправлення логічних помилок. Текст простої програми на Асемблері містить наступні операції: - команди або інструкції конкретного МП, які реалізовують алгоритм; - директиви (або псевдооператори) Асемблера, які резервують пам’ять для змінних і описують необхідні для роботи програми константи; - оператори; - наперед визначені імена.
342 5.6. Формат команд Асемблера 5.6. Формат команд Асемблера Кожну команду (інструкцію) записують в окремому рядку. Вона може містити до чотирьох полів. Не обов’язкові поля нами виокремлено символами “[“ і [ Мітка ] Мнемоніка команди [ Ottepand{u) ] [; Коментар ] • Мітка або символічна адреса може містити до 31-го символу, серед яких є літери, цифри і символи. “?”, Причому цифра не повинна стояти першою, а крапка, якщо вона є, повинна стояти першою. • Мнемоніка - скорочене позначення коду операції (КОП) команди. Наприклад, мнемоніка ADD позначає додавання {Addition). • Операндами можуть бути двійкові набори, які задаються явно або неявно і над якими виконуються операції. Операнди наводять в одній із чотирьох систем числення, їх необхідно закінчувати малим (чи великим) символом: b{B), о{0), d{D), h{H) для 2-ї, 5-ї, 10-і або у 16-і системи числення, відповідно. Якщо шістнадцяткове число розпочинається з літери, то зліва до нього додається нуль. Систему команд можна класифікувати за трьома головними ознаками: довжиною команди (число байтів, які вона займає); її функціональним призначенням; способом адресування. /«^/-сумісний мікропроцесор обробляє команди довжиною від одного до шести байт. Перший байт кожної команди налічує код команди, який визначає її функцію, тобто алгоритм її роботи. За функціональною ознакою команди поділяють на п’ять груп: команди пересилання даних; арифметичні команди; логічні команди; команди переходів; команди управління. Розрізняють п’ять головних способів адресування даних: регістровий; безпосередній; прямий; непрямий; стековий.
\ 5. ЗВ’ЯЗОК PASCAL-ACEMEnkp 343 5.7. Логічні основи роботи Intel-сумісних МП 5.7.1. Регістри МП Програмування на Асемблері неможливе без чіткого розуміння програмної моделі того МП, з яким програміст має намір працювати. У випадку програмування мовою Borland Pascal - це сім’я /б-розрядних/яґе/-сумісних МП. Оскільки всі сучасні ПК, які сьогодні доступні нам, побудовано на 52-розрядних МП, нижче наведено власне цю модель, хоча ми наразі використовуватимемо тільки її іб-розрядну частину. На повноцінній 52-розрядній моделі працює середовище Delphi [9, 54], мовою програмування якого є Object Pascal. Регістри загального призначення Розрядність процесора визначають за довжиною в бітах його регістрів загального призначення (РЗП). Програмуючи на Асемблері, програміст використовує регістри при написанні своїх програм. В РЗП під час роботи програми зберігаються проміжні дані та адреси початкових байтів певних ділянок ОП. Конфігурацію РЗП наведено на рис. 5.1. 31 16 8 о еАх Ах Ah 1 Al еВх Вх Bh ВІ еСх eDx еВр eSp eDi eSi Сх Ch \ Cl Dx Dh | Dl Bp Sp Di Si Accumulator register Base register Count register Data register Base Pointer register Stack Pointer register Destination Index register Source Index register Рис. 5.1. Регістри загального призначення //^/-сумісного МП
344 5.7. Логічні основи роботи //iteZ-сумісних МП Кожен із перших чотирьох регістрів фактично містить у собі чотири частини, які залежно від потреби, використовують по різному. Цифри 0, 8, 16, які стоять зверху, вказують на початкові номери бітів кожної частини відповідного регістра. Цифра 31 - це номер останнього біта. Під час роботи з S-розрядними числами їх можна заносити або у нижню праву частину, яку позначено літерою /, або у верхню праву частину, яку позначено літерою А. Такий поділ регістрів передбачено з метою забезпечення праце-здатності програм, написаних для молодших /б-розрядних моделей мікропроцесорів фірми Intel, починаючи з І8086. Префікс е (extended) означає розширений. Зазначимо, що використовувати для самостійного адресування можна тільки молодші 16-бітові частини цих регістрів. Старші 16 біт, як самостійні частини, програмістові для програмування недоступні. Оскільки ці регістри фізично розташовані всередині частини МП, яку називають арифметико-логічним пристроєм (АЛП), то їх, відповідно, називають регістрами АЛП. Опишемо функціональне призначення регістрів. Арифметичні регістри їх застосовують під час виконання більшості арифметичних операцій. еАх еВх еСх eDx 31 *! 15 7 0 Ах Ah АІ ► Вх Bh BL Accumulator register Base register Сх Ch СІ Dx Dh Dl Count register Data register Рис. 5.2. Арифметичні регістри eAx/Ax/Ah/Al (Accumulator register) - акумулятор. Застосовують для зберігання проміжних даних. У деяких командах використання цього регістра є обов’язковим.
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 345 • eBx/Bx/Bh/Bl (Base register) - базовий регістр. Застосовують для зберігання базової (початкової) адреси деякої ділянки ОП. • eCx/Cx/Ch/Cl (Count register) - регістр-лічильник. Застосовують у командах, що виконують деякі дії, які повторюються. Здебільшого його використання в алгоритмі роботи відповідної команди є неявним (прихованим). Наприклад, команда організації циклу Loop окрім надання управління початковій команді тіла циклу, що знаходиться за деякою адресою, аналізує та автоматично зменшує на одиницю вміст регістра еСх/Сх. • eDx/Dx/Dh/DI (Data register) - регістр даних. Так само, як і акумулятор, він зберігає проміжні дані. В деяких командах його використання є обов’язковим. Для певних команд це відбувається неявно. Індексні регістри Наступні два регістри (рис. 5.3) використовують з метою підтримки так званих ланцюжкових операцій, тобто операцій, що виконують послідовну обробку ланцюжків елементів ОП, кожен з яких може мати довжину 32,16 або 8 біт. 31 16 « еЫ eSi Di Si Destination Index register Source Index register Рис. 5.3. Індексні регістри eDi/Di (Destination Index register) - індексний регістр приймача (одержувача) даних. В ланцюжкових операціях містить поточну адресу в ланцюжку-приймачі. eSi/Si (Source Index register) - індексний регістр джерела даних. Цей регістр у ланцюжкових операціях містить поточну адресу елемента в ланцюжку-джерелі. Вказівникові регістри В архітектурі МП на програмно-апаратному рівні підтримується така структура даних, як стек. Для роботи зі стеком в
346 5.7. Логічні основи роботи //ffeZ-сумісних МП системі команд МП є спеціальні команди, а в програмній моделі МП з цією метою передбачено окремі регістри (рис. 5.4). зі їв eSp еВр Sp Вр Stack Pointer register Base Pointer register Рис. 5.4. Вказівникові регістри • eSp/Sp (Stack Pointer register) - регістр вказівника стека. Містить вказівник вершини поточного сегменту стека. • еВр/Вр (Base Pointer register) - регістр вказівника бази кадру стека. Призначений для організації довільного доступу до даних усередині стека. Зауважимо, що таке жорстке функціональне призначення регістрів АЛП не завжди є обов’язковим. Здебільшого при програмуванні їх можна використовувати для зберігання операндів практично в будь-яких поєднаннях. Проте, як уже зазначалось, деякі команди використовують фіксовані регістри для виконання своїх дій, що необхідно обов’язково враховувати під час програмування на Асемблері. Знання цих особливостей даватиме змогу, за необхідності, хоча б на декілька байт заощадити пам’ять, яку займає код програми. % Сегментні регістри У програмній моделі мікропроцесора є шість сегментних регістрів: Cs, Ds, Ss, Es, Gs, Fs (рис. 5.5). їхнє існування зумовлено специфікою організації і способом використання ОП мікропроцесорами фірми Intel. Вона полягає в тому, що МП апаратно підтримує структурну організацію програми у вигляді трьох частин, що називають сегментами: дані, код, стек. Відповідно, таку організацію пам’яті називають сегментною. Сегментні регістри призначені для того, щоб вказати на сегменти, до яких програма має доступ у конкретний момент часу. Фактично у цих регістрах містяться адреси пам’яті, з яких починаються відповідні сегменти. Логіка обробки машинної команди побудована так, що під час вибірки команди чи доступу до даних програми або до стека неявно використовуються адреси, які записані у сегментних регістрах.
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 347 15 Cs Ds Ss Code segment register Data segment register Stack segment register Extension data segment registers Рис. 5.5. Сегментні регістри Опишемо функціональне призначення сегментів програми: Сегмент коду містить команди програми. Для доступу до цього сегмента слугує регістр Cs {Code segment register) - сегментний регістр коду. Він містить адресу сегмента з машинними командами, до якого має доступ МП (тобто ці команди завантажуються у конвеєр МП). Сегмент даних містить дані, які обробляє наша програма. Для доступу до цього сегмента слугує регістр Ds (Data segment register) - сегментний регістр даних, який зберігає адресу сегмента даних поточної програми. Сегмент стека. Цей сегмент є областю пам’яті, яку називають стеком. Роботу з нею МП організовує за таким принципом: останній записаний в цю область елемент читається першим. Для доступу до цього сегмента слугує регістр Ss (Stack segment register) - сегментний регістр стека, що містить адресу початку сегмента стека. Часто у літературі стек називають магазином, оскільки принцип його дії подібний до роботи магазину стрілецької автоматичної зброї: першим добувається і потрапляє у ствол набій, який закладено туди останнім. Аналогічно, зі стека першими читаються ті дані, які у стек потрапили останніми. Принцип “останнім зайшов - першим вийдеш” скорочено позначають LIFO (Last In - First Out).
348 5.7. Логічні основи роботи /несумісних МП Додаткові сегменти даних. Алгоритми виконання більшості машинних команд неявно допускають, що оброблювані ними дані розташовані в сегменті даних, адресу якого подано в сегментному регістрі Ds. Якщо програмі недостатньо одного сегмента даних, то вона може використовувати ще три додаткові сегменти даних. Однак, на відміну від головного сегмента даних, адреса якого міститься в Ds, під час використання додаткових сегментів даних їхні адреси необхідно зазначати явно за допомогою спеціальних префіксів перевизначення сегментів у команді. Адреси додаткових сегментів даних повинні міститися в регістрах Es, Gs, Fs {Extension data segment registers). Регістри стану та управління 7/і/е/-сумісний МП має декілька регістрів, які постійно містять інформацію про стан як самого МП, так і програми, команди якої в даний момент завантажені на конвеєр. Використовуючи ці регістри, можна одержувати інформацію про результати виконання команд і впливати на стан самого МП. До цих регістрів належать регістри eFlags/Flags та еір/ір (рис. 5.6). 31 16 0 eFlags еір Flags *1 ІР Flags register Instruction Pointer register Рис. 5.6. Регістри стану та управління • eFlags/Flags (Flag register) регістр прапорців. Його розрядність - 32/16 біт. Окремі біти цього регістра мають певне функціональне призначення, їх називають прапорцями. Молодша частина цього регістра цілком аналогічна регістрові Flags МП І8086.
5. ЗВ’ЯЗОК PASCAL-ЛСЕМБЛЕР 349 У табл. 5.1 подано структуру регістра Flags. Таблиця 5.1 Структура регістра прапорців Flags 15 0 .• 14 NT Прапорець вкладеності задачі 13 IOPL Рівень привілейованості введення/виведення 12 11 OF Прапорець переповнення 10 DF Прапорець напряму 09 IF Прапорець переривання 08 TF Прапорець трасування 07 SF Знаковий прапорець 06 ZF Прапорець нуля 05 0 04 AF Допоміжний прапорець перенесення 03 0 02 PF Прапорець парності 01 1 00 CF Прапорець перенесення Виходячи з особливостей використання, прапорці регістра Flags можна розділити на три групи: І.Вісім прапорців стану. Ці прапорці можуть змінюватися після виконання певних машинних команд. Вони відображають особливості результату виконання арифметичних або логічних операцій. Це дає змогу аналізувати стан обчислювального процесу і реагувати на нього за допомогою команд умовних переходів чи викликів підпрограм. • CF (Carry Flag) - прапорець перенесення. Містить /, якщо арифметична операція здійснила перенесення зі старшого біта результату. Старшим є 7-й, /5-й або 31-й біт, залежно від довжини операнда. • PF (Parity Flag) - прапорець парності. Містить 7, якщо 8 молодших розрядів результату містять парне число одиниць (цей прапорець відповідає тільки за 8 молодших розрядів операнда будь-якого розміру). • AF (Auxiliary Carry Flag) - допоміжний прапорець перенесення. Тільки для команд, які працюють з BCD- числами. Фіксує факт позичання з молодшої тетради
350 5.7. Логічні основи роботи /nteZ-сумісних МП результату. Якщо 1 - в результаті операції додавання було виконано перенесення з розряду 3 в старший розряд або при відніманні була позика в розряд 3 молодшої тетради із значення у старшій тетраді; 0 - перенесень у третій розряд і позик з 5-го розряду молодшої тетради результату не було. • ZF (Zero Flag) - прапорець нуля. Якщо 1 - результат нульовий; 0 - результат ненульовий. • SF (Sign Flag) - знаковий прапорець. Відображає стан старшого біта результату (біти 7, 15 або 31 для 8-, 16- або 32-розрядних операндів, відповідно): 1 - старший біт результату дорівнює 1; 0 - старший біт результату дорівнює 0. • OF (Overflow Flag) - прапорець переповнення. Використовують з метою фіксування факту втрати значущого біта при арифметичних операціях: Якщо 1 - в результаті операції відбувається перенесення у старший (позика зі старшого) знакового біта результату (біти 7, 15 або 31 для 8-, 16- або 32-розрядних операндів, відповідно); 0 - в результаті операції не відбувається перенесення у старший (позика зі старшого) знакового біта результату. • ЇОРЬ (Input/Output Privilege Level) - рівень привілейованості введення/виведення. Використовують у захищеному ^режимі роботи МП з метою контролю доступу до команд введення/виведення залежно від рівня пріоритету задачі. • NT (Nested Task) - прапорець вкладеності задачі. Використовують в захищеному режимі роботи МП для фіксації того факту, що одну задачу вкладено в іншу. 2. Один прапорець управління. Позначається Df (Directory Flag). Він перебуває у 10-му біті регістра Flags (використовується ланцюжковими командами). Значення прапорця Df визначає напрям поелементної обробки в цих операціях: від початку рядка до кінця, або навпаки - від кінця рядка до її початку (Df= 1). Для роботи з прапорцем Df існують спеціальні команди: Cld (зняти прапорець Df) і Std (встановити прапорець Df). Застосування цих команд дає змогу привести прапорець Df у відповідність з алгоритмом і забезпечити автоматичне збільшення чи зменшення лічильників виконання операцій з рядками.
5. ЗВ’ЯЗОК PASCAL-ACEMEJIEP 351 3. Два системних прапорці, що управляють введенням/виведенням, маскованими перериваннями, налагодженням, перемиканням між задачами і віртуальним режимом МП І8086. Прикладним програмам не рекомендовано модифікувати без необхідності ці прапорці, оскільки, здебільшого, це спричинить до переривання роботи програми. Нижче перелічено системні прапорці та описано їхнє призначення. • TF {Trace Flag) - прапорець трасування. Призначений для організації покрокової роботи МП. Якщо 1 - МП генерує переривання з номером 1 після виконання кожної машинної команди. Може використовуватися під час налагодження програм, зокрема налагоджувачами; 0 - звичайна робота. • IF {Interrupt enable Flag) - прапорець переривання. Призначений для дозволу або заборони (маскування) апаратних переривань (переривань по входу INTR). 0 - апаратні переривання заборонено. Примітка. 16-и, /7-й та 18-й біти регістра eFlags/Flags містять ще три системні прапорці, які ми не розглядатимемо. elp/Ip {Instruction Pointer register) - регістр вказівника команди). Він має розрядність 32/16 біт (рис. 5.6) і містить зміщення наступної команди, яка підлягає виконанню, щодо вмісту сегментного регістра Cs у поточному сегменті команд. Цей регістр безпосередньо недоступний програмістові, проте завантаження і зміну його значення здійснюють різними командами управління, до яких належать команди умовних і безумовних переходів, виклику процедур і повернення з процедур. Виникнення переривань також спричинить до модифікації регістра еІр/Тр. 5.7.2. Типи даних При програмуванні на Асемблері використовують дані таких типів: 1. Безпосередні дані або константи. Вони є одним із операндів команди Асемблера і містять числові чи символьні значення. Формуються програмістом під час написання конкретної команди програми. 2. Прості {скалярні) дані. Описуються за допомогою директив резервування пам’яті. Дають змогу виконати елементарні
352 5.7. Логічні основи роботи 7/і^/-сумісних МП операції з розміщення та ініціалізації числової чи символьної інформації. При асемблюванні цих директив Асемблер формує таблицю символів, куди заносить інформацію про сегментну складову адреси даного, величину його зміщення щодо початку сегмента і тип даного, тобто кількість одиниць пам’яті, виокремлених для його розміщення відповідно до конкретної директиви його резервування та ініціалізації. Ці два типи даних є елементарними, або базовими. Робота з ними підтримується на рівні системи команд мікропроцесора. Використовуючи дані цих типів, можна формалізувати і запрограмувати практично будь-яку задачу. 3. Структуровані дані використовують при роботі з масивами чи записами. їх введено в Асемблер з метою спрощення процесу розробки програм. Ці типи даних будують на основі базових типів, які слугують “цеглинками” для їхньої побудови. Наявність структурованих даних дещо згладжує розбіжності між мовами високого рівня та Асемблером. Однією з безперечних переваг мов високого рівня є підтримка розвинених структур даних, оскільки за їхнього використовування програміст звільняється від необхідності розв’язання проблем, що стосуються представлення числових або символьних даних, і має змогу оперувати інформацією, структура якої значною мірою відображає особливості предметної області задачі, що розв’язується. З іншого боку, чим вищий рівень абстракції даних, тим більше навантаження лягає на компілятор у сенсі створення дійсно ефективного коду, Адже все, що написано на мові високого рівня, після компілювання буде представлене як машинні команди, які працюють тільки з базовими типами даних. Отже, найефективніша програма - програма, написана в машинних кодах, однак писати сьогодні всю велику програму в машинних кодах недоцільно. Поняття простого типу даних має подвійне трактування. З погляду розрядності (<фізична інтерпретація), МП апаратно підтримує такі типи даних (рис. 5.7):
5. ЗВ’ЯЗОК РАБСАЬ-А СЕМБЛЕР 353 Байт ■■■■---~Слі Ст. байт 7во== Мол. байт | Подвійне Старше слово слово Молодиі е слово —^-^—--—-Почетверенне слово-—™-" = Старше подвійне слово Молодше пі 1 1 во 4в 32 16 8 0 Рис. 5.7. Базові типи даних /и*е/-сумісного МП • Байт - вісім послідовно розташованих бітів, пронумерованих від 0 до 7, при цьому біт 0 є наймолодшим значущим бітом. • Слово - послідовність з двох байтів (76-ти бітів), що мають суміжні адреси. Біти у слові нумеруються від 0 до 15. Байт, що містить нульовий біт, називають молодшим байтом, а байт, що містить /5-й біт - старшим байтом. В /и*е/-сумісних МП молодший байт завжди зберігається за меншою адресою. Адресою слова вважають адресу його молодшого байта. Адресу старшого байта можна використати для доступу до старшої половини слова. • Подвійне слово - послідовність з чотирьох байтів (32-х бітів), розташованих за суміжними адресами. Нумерація бітів здійснюється від 0 до 31. Слово, що містить нульовий біт, називають молодшим словом, а слово, що містить 31-й біт, - старшим словом. Молодше слово зберігається за меншою адресою. Адресою подвійного слова вважають адресу його молодшого слова. Адресу старшого слова використовують для доступу до старшої половини подвійного слова. • Почетверене слово - послідовність з восьми байтів {64-х бітів), розташованих за послідовними адресами. Нумерація бітів здійснюється від 0 до 63. Подвійне слово, що містить нульовий біт, називають молодшим подвійним словом, а подвійне слово, що містить 63-й біт, - старшим подвійним словом. Молодше подвійне слово зберігається за меншою адресою. Адресою почетвереного слова вважають адресу його молодшого подвійного слова. Адресу старшого подвійного слова використовують для доступу до старшої половини почетвереного слова. 12 7-451
354 5.7. Логічні основи роботи /и<е/-сумісних МП Окрім трактування типів даних з погляду їхньої розрядності, МП на рівні команд підтримує логічну інтерпретацію цих типів (рис. 5.8): ЗІБойт ! ЩІііЖШІЯ ji Сяово Подвійне слово ЩШШттШШттМї ШШШШШж-v" -ЗІ ПодвШнесяом а б Рис. 5.8: Типи: а — цілий беззнаковий; б — цілий зі знаком • Цілий беззнаковий тип - двійкове значення без знака, розміром 8, 16 або 32 біта (рис. 5.8, а). Зазначимо числовий діапазон для цього типу: — байт - від 0 до 255 = 2S-1; — слово - від 0 до 65 535 = 2І6-1; — подвійне слово - від 0 до 4 294 967295 = 2?2-1. • Цілий тип зі знаком - двійкове значення зі знаком, розміром 8, 16 або 32 біта. Знак чисел цього типу міститься у 7-у, 15-у або 31-у біті, відповідно. На рис. 5.8, б його позначено літерою 3. Нульове значення знакового біта відповідає додатному числу, а одиниця - від’ємному. Від’ємні числа представляються в доповняльному коді. Запишемо числові діапазони для цього типу даних: — 8-розрядне ціле - від -128 до +127; — 16-розрядне ціле - від -32 768 до +32 767; — 32-розрядне ціле - від -231 до +231-!. • Вказівник одного з двох типів: — типу ближній (Near); містить 52-розрядну логічну адресу, що є відносним зміщенням у байтах від початку сегмента;
5. ЗВ’ЯЗОК PASCAL-ACEMEJIEP 355 — типу дальній (Far); містить 45-розрядну логічну адресу, яка складається з двох частин: іб-розрядної сегментної частини - селектора, і 32-розрядного зміщення (зміщення займає молодші 32 розряди, селектор - старші 16 розрядів). • Ланцюжок - неперервний набір байтів, слів чи подвійних слів. Максимальна довжина ланцюжка - до 4Гб. • Бітове поле є неперервною послідовністю бітів, у якій кожен біт є незалежним і може розглядатися як окрема змінна. Бітове поле може починатися з будь-якого біта будь-якого байта і містити до 32-х біт. • Незапаковане двійково-десяткове (BCD) число - побай- тове представлення десяткової цифри від 0 до 9. Незапаковані десяткові числа зберігаються як байтові значення без знака по одній цифрі в кожному байті. Значення цифри визначається молодшим півбайтом. ОООй BCD і . . \000d, BCD od 0000, BCD І0000І BCD “ 24 a 0 Рис. 5.9. Незапаковане двійково-десяткове (BCD) число Запаковане двійково-десяткове (BCD) число є запакованим представленням двох десяткових цифр від 0 до 9 в одному байті. Кожна цифра зберігається у своєму півбайті. Цифра у старшому півбайті (бітах 4-7) є старшою. BCD і BCD', . . . . і BCD\ BCD| BCD\ BCD \ BCD iff т BCD Рис. S. 10. Запаковане двійково-десяткове (BCD) число 5.7.3. Опис та ініціювання даних Програми асемблювання TASM.exe чи MASM.exe надають програмістові широкий набір засобів опису та обробки даних, які відповідають аналогічним засобам мов програмування високого рівня. Для опису простих типів даних використовують спеціальні директиви резервування та ініціювання даних, які, зазвичай, є
356 5.7. Логічні основи роботи /и*е/-сумісних МП вказівками Асемблеру на виокремлення певного об’єму пам’яті. Асемблер, обробляючи кожну таку директиву, виокремлює кожній змінній необхідну кількість байт пам’яті і, за необхідності, заповнює цю область необхідним початковим значенням. Директиви резервування та ініціювання даних простих типів мають такий формат: < Ім'я > < Назва, директиви > < Вираз > . Кожне з трьох полів може містити таку інформацію: • ім'я - деяке символічне ім’я елемента пам’яті в сегменті даних, яке використовуємо у програмі як змінну. • Назва директиви містить одну із наступних мнемонік: S db - резервування пам’яті для даних розміром 1 байт. Можна задавати наступні значення: о вираз або константу, що набуває значення з діапазону: -128..+127 для чисел зі знаком і - 0..255 для беззнакових чисел; о S-бітовий відносний вираз, що використовує операції HIGH і LOW; о символьний рядок з одного чи кількох символів. Рядок беремо в лапки. У цьому випадку визначається стільки байт, скільки символів у рядку. * S dw - резервування пам’яті для даних розміром 2 байти. Цією директивою можна задавати наступні значення: о вираз або константу, що набуває значення з діапазону: -32768.32767 для чисел зі знаком і - 0..65535 для беззнакових чисел; о вираз, що займає 16 або менше бітів, який може слугувати зміщенням у /б-бітовому сегменті або самою адресою сегмента; о /- або 2-байтовий рядок у лапках. S dd - резервування пам’яті для даних розміром 4 байти. Директивою задають наступні значення:
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 357 о вираз або константу, що набуває значення з діапазону: -32 768..+32 767 для чисел зі знаком і 0..65 535 для чисел без знака (для іб-розрядних МП); і, відповідно, для чисел зі знаком -2 147 483 648.Л2 147 483 647 та для беззнакових чисел 0..4294967295 (для 32-розрядних МП); о відносний або адресний вираз, що складається з іб-бітової адреси сегмента і /б-бітового зміщення; о рядок завдовжки до 4-х символів у лапках. S dfidp резервування пам’яті для даних розміром б байт; ■S dq - резервування пам’яті для даних розміром 8 байт. S dt- резервування пам’яті для даних розміром 10 байт. Обробляючи зарезервовані названими директивами дані, необхідно пам’ятати порядок розміщення даних у пам’яті. Intel- сумісні МП вимагають розташування даних у пам’яті за принципом: молодший байт розташований за молодшою адресою. • Вираз може набувати таких значень: S ? вказує, що вміст поля не визначено; відбувається тільки резервування необхідної кількості байт без заповнення зарезервованого поля значенням; S значення ініціалізації - значення елемента даних, яке буде занесено в пам’ять після завантаження програми; фактично створюється змінна, початкове значення якої задають на етапі створення програми (цим способом можна також задати константу); S формула - <N повторень> DUP (значення ініціалізації) - ітеративна конструкція, яка дає змогу повторити N разів послідовне занесення у фізичну пам’ять виразу, який стоїть у дужках. Нижче наведено приклад фрагмента проасембльованого сегмента даних з різними способами опису та ініціювання даних:
358 5.7. Логічні основи роботи /«^/-сумісних МП Зміщення Результат компілювання Директиви Асемблера у форматі: <ім’я> <назва директиви> <вираз> DATASEG 0000 0014 0007 0004 0005 0003 Dani Dw 20,7,4, 3,5 00 0А 00 Dxc Db 0 ооов 000000000006 Two Df 6 0011 00000006 00000007 Three Dd 6,7 0019 ???? Dat Dw ? 001В OD 0А 50 72 69 65 72 20 6Е 6F 72 65 61 64 79 21 21 OD 0А 24 6Е 74 20 74 20 21 МБОЗ пс^ Db 13,10, ready !!! ' 'Printer , 13, 10, 0035 3A7F Р_2 Dw 3a7fh 0037 F54D567A Р_3 Dd Of54d567ah 003В 0А* (20) МаБ Db 10 DUP (' ') 0045 % 05*(??) Р11 Db 5 DUP (?) Усі дані у двох лівих стовпцях подано у шістнадцяткових числах. Власне так виглядатиме фрагмент ОП, що містить наведений сегмент даних.
5. ЗВ’ЯЗОК PASCAL-ЛСЕМБЛЕР 359 5.8. Робота 3 оперативною пам'яттю Пам’ять Intel-сумісних МП поділяється на біти (1 двійковий розряд), байти (8 бітів), слова (16 бітів) і подвійні слова (32 біти). Слова розташовані у двох суміжних байтах. Адресою слова є адреса його молодшого байта. Відповідно, подвійне слово записується у чотири суміжні байти. Адресою наймолодшого із цих чотирьох байтів вважають адресу подвійного слова. Більшими одиницями поділу пам’яті є сегменти і сторінки. Пам’ять логічно може поділятись на сегменти змінної або фіксованої довжини. У захищеному режимі роботи мікропроцесора можливе розбиття пам’яті на сторінки. Сегментування є засобом організації логічної пам’яті з погляду прикладної програми. Розбиття на сторінки застосовується на системному рівні для управління фізичною пам’яттю. Логічна або віртуальна адреса будь-якого елемента ОП складається із двох частин: адреси початку сегмента і ефективної адреси, або так званого зміщення (offset). Сегментування пам’яті поділяє весь адресний простір у 20-бітний простір лінійних (фізичних) адрес (для /б-розрядних МП) або у 32-бітний простір фізичних адрес (для 52-розрядних МП). Для зберігання адрес початків сегментів пам’яті різного функціонального призначення використовують чотири сегментні регістри: Cs, Ss, Ds, Es. Щоб утворити фізичну 20-бітну адресу, МП об’єднує значення, записані у сегментному регістрі зі значенням зміщення, яке перебуває в іншому РЗП. У цьому випадку значення зміщення зсувається на 4 розряди ліворуч (тобто множиться на 16=2\ що є те саме) і додається до значення, що є у сегментному регістрі. Результатом є 20-розрядне число - фізична адреса конкретного байта пам’яті. Сегменти мають такі властивості: • межі сегментів кратні 16; • максимальна довжина сегмента пам’яті для /6-розряд- ного МП має 64Кб; мінімальна довжина - 16 байт; • в 1Мб пам’яті можна вказати 65 536 різних меж сегментів; • сегменти в ОП фізично не існують. Вони є логічними вікнами, завдяки яким програми оперують із пам’яттю;
360 5.8. Робота з оперативною пам’яттю • сегменти у пам’яті не обов’язково розташовані один за одним, вони можуть частково або цілком перекриватись один з одним: один і той самий байт пам’яті може мати різні логічні адреси, які задаються різними парами сегментгзміщення (проте, в кінцевому результаті, всі вони дають одну і ту саму фізичну адресу цього байта пам’яті). Початок сегмента коду програми записується автоматично у регістр Cs, при завантаженні програми у пам’ять. Зміщення для цього сегмента перебуває у регістрі Ір. Початок сегмента стека автоматично заноситься у регістр Ss. Зміщення - в Sp. Завантаження початку сегмента даних у регістр Ds або Es в Асемблері забезпечує програміст. Фізичну адресу, обчислену на підставі вмісту двох регістрів, називають далекою адресою {far address). Інколи для адресування комірки пам’яті використовують лише значення зміщення. Таку адресу називають ближньою (near address). Оскільки у /d-розрядний регістр можна помістити число, що не перевищує 64Кб, то воно слугує обмеженням зверху як для значення зміщення, так і для довжини сегмента. Формування ближньої адреси здійснюється мікропроцесором значно швидше ніж далекої. 5.8.1. Моделі пам'яті Кожна асемблерна програма налічує три ділянки: код, дані і стек. Взаємне розташування у пам’яті сегментів коду, даних і стека визначається програмістом шляхом явного задавання так званої моделі пам’яті. За її посередністю Асемблер визначає, за замовчуванням, розмірність деяких операцій і даних, що використовуються у програмі. 7«/е/-сумісні МП розрізняють 7 різних моделей: • Tiny. Вся програма розміщена в межах одного сегмента. Регістри Cs, Ss, Ds містять одне і те саме значення. Така модель відповідає со/и-файлові. Це найкомпактніший і найшвидший варіант програми. Асемблер тут генерує тільки близькі адреси з використанням одного зміщення. Модель використовується при розробці резидентних програм.
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 361 • Small. Код розташований в окремому Сегменті, що дає змогу формувати ближні адреси переходів. Стек і дані об’єднані в один сегмент. Регістри Ds і Ss містять одне і те ж значення. • Compact. Модель використовує один сегмент коду і декілька сегментів даних. Усі переходи в межах програми мають адресування типу near, а звертання до даних у пам’яті - типу far. • Medium. У певному аспекті ця модель є протилежністю до попередньої. Вона використовує декілька сегментів коду та один сегмент даних, що містить у собі сегмент стека. Доступ до адрес команд програми є типу far. • Large є узагальненою моделлю організації пам’яті. Вона передбачає декілька сегментів даних і декілька сегментів коду. Все адресування відбувається із використанням далеких адрес. • Huge. Модель має організацією пам’яті, подібну до моделі Large. Використовується для узгодження підпрограм, що написані на різних мовах високого рівня. При програмуванні на Асемблері її бажано не використовувати. • Flat - цілковито відповідає моделі Small, однак використовує (для визначення зміщень) 52-розрядні регістри. Застосовується у 52-розрядних МП при програмуванні захищеного режиму їхньої роботи. Модель Flat називають плоскою (безсегментною) пам’яттю. Тут за допомогою одного сегмента забезпечується доступ до фізичного масиву ОП загалом. 5.8.2. Адресування даних у пам'яті /«/^/-сумісні МП забезпечують таке адресування даних у пам’яті: І.Пряме адресування. Якщо джерело або приймач розташовані у пам’яті у сегменті даних, то команди Асемблера читання/запису цих даних мають такий формат: <КОП> <РЗП>, [ім'я змінної] або
362 5.8. Робота з оперативною пам’ятпо <КОП> [ім'я змінної], <РЗП>: ,ДЄ • коп - код операції (ім’я команди Асемблера)', • рзп - регістр загального призначення; • [ім'я змінної] - символічне ім’я елемента пам’яті, описане в сегменті даних. Такий запис асемблюється у зміщення адреси зазначеного елемента відносно початку сегмента даних. Адреса його початку розташована у регістрі Ds. Наприклад: Dataseg ; Початок сегмента даних Four Dw 4 ; Опис елемента (слова) пам’яті Codeseg ; Початок сегмента коду Mov Ах, [Four] ; Завантаження вмісту слова пам’яті в акумулятор. Регістр, що містить початок сегмента даних, можна перепри- значити. Наприклад, команда Mov Ch., [£s:Dt] запише у старший байт лічильника Сх байт, який має ім’я Dt і перебуває у сегменті, що базується сегментним регістром Ез, якого ми таким способом перепризначили замість регістра Da. На місці регістра Ез можна поставити Сз або Sa. Тоді запис/читання відбудеться, відповідно, із сегмента коду, чи сегмента стека. Необхідно пам’ятати, що: • перепризначення є дійсним тільки в межах однієї команди; • • використання квадратних дужок необхідне тільки для режиму Ideal, тобто в разі використання програми Tasntexe. Асемблер Masntexe передбачає дещо вільніший стиль запису операндів; • відповідальність за те, щоб змінні знаходились у відповідних сегментах, несе програміст. 2. Неявне адресування. Замість звертання до змінної за її іменем тут, для вказівки на дані в пам’яті, використовують один із трьох регістрів: Вх, Si або ві. Оскільки вміст кожного з цих регістрів можна регулярно змінювати, такий спосіб адресування дає змогу обробляти однією і тією самою командою кожен раз інше число. Після завантаження в один із названих регістрів (наприклад, вх) зміщення деякої змінної ми зможемо доступитись до її значення, наприклад, так:
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 363 Mov Ах, [Word Вх]. Ця команда записує в акумулятор слово оперативної пам’яті, на яке вказує регістр Вх. Dec [Byte s±]. Зменшення на 1 значення числа, зміщення якого було попередньо записано в регістр si. Ключові слова типу Word або Byte є необхідними, оскільки Асемблер сам не може визначити кількість байт. У першій команді наявність слова Word не є обов’язковою. Слово Byte у другій команді - обов’язкове. За неявного адресування сегментним регістром за замовчуванням неявно слугує регістр Ds. Наведемо декілька прикладів використання даного типу адресування: Add [Word Es: Вх], 5 ; додавання числа 5 до вмісту слова пам’яті, яке адресоване парою регістрів Es:Bx. Inc [Byte Ss: Si] ; збільшення на 1 вмісту байта пам’яті, адреса якого задається парою регістрів Ss: Si. Mov Ах, [Cs: Di] ; завантаження в акумулятор слова із сегмента коду. 3. Базове адресування. Використовує регістри Вх і Вр. При цьому регістр Вх - для доступу до значень сегмента даних, який базується регістром Ds, а Вр, в парі з Ss - для роботи зі стеком. За цього способу адресування до зміщення, записаного в Вх чи Вр, додається значення зсуву, задане додатним або від’ємним цілим числом. Це число забезпечує доступ до значення, розташованого у пам’яті вище або, відповідно, нижче адреси, яка визначається парою регістрів DsiBx чи SsiBp. Базове адресування використовують для доступу до елементів масиву. Наприклад, команда: MOV Ах, [Вх + 4] надішле в акумулятор вміст слова пам’яті, що розташоване на 4 байти вище адреси, на яку вказує вміст регістра Вх, а команда: DEC [Byte Вр - 8] зменшить на7 відповідне значення у стеку. 4. Індексне адресування. Його механізм подібний до базового, проте адреса зсуву міститься в регістрі si або Di. Якщо не виконано перепризначення базового регістра, всі звертання до адрес, що індексуються, проходять відносно сегмента даних, який базується регістром Ds. Цей тип адресування використовують для доступу до елементів простих масивів. Наприклад, команда: INC [Byte Si+4]
364 5.8. Робота з оперативною пам’яттю збільшить на 1 вміст п’ятого байта байтового масиву, оскільки адреса 51+0 вказує на перший елемент масиву. 5. Базово-індексне адресування. Тут об’єднуються значення двох регістрів, до яких може додаватися необов’язковий числовий зсув. Це фактично є одночасним застосуванням двох попередніх видів адресування. Першим регістром має бути Вх або Вр, а другим - 51 або Гі. Щодо цього Вх містить зміщення відносно значення регістра Дз, а Вр, відповідно, - відносно Бв. У цьому виді адресування можливе також перепризначення регістрів. Таке адресування використовують під час обробки складних структур даних. Наприклад: Мслг Ах, [Вх+5і] або Молг Ах, [Вх+Ві] ; завантаження слова із сегмента даних. Молг Ах, [Вх+51+12] або Молг Ах, [Вх+Ві+8] ; завантаження слова із сегмента даних із зсувом. Мотг Ах, [Вр+5і] або МсАх, [Вр+Ві] ; завантаження слова із сегмента стека. 5.9. Система команд У таблицях, які наведено нижче, подано стислий опис базових команд Іпїеі-сумісних МП. Команди поділено на 6 функціональних груп: переміщення даних; арифметичні,; побітові; рядкові; передачі управління, переривань. Усередині кожної групи команди об’єднуються в підгрупи за загальними додатковими ознаками. 5.9.1. Команди переміщення даних Назва Формат запису Функції ь ( Команди загального призначення MOV MOV приймач, джерело Копіює значення джерела у приймач PUSH PUSH джерело Копіює в стек значення джерела POP POP приймач Виштовхує зі стека значення у приймач XCHG XCHG приймач, джерело Обмінює значення приймача і джерела XLAT XLAT таблиця Завантажує в А1 байт з таблиці у пам’яті
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 365 Команди введення/виведення IN IN акумулятор, ПОТУГ Читає з порту введення/виведення акумулятор OUT оит порт, акумулятхю Записує у порт значення акумулятора Команди пересилання адреси LEA LEA регістрі 6, пам’ятьіб Завантажити виконавчу адресу LDS LDS регістрі 6, память32 Завантажити в :регістрі 6 повну алоесу LES LES регістрі 6, память32 Завантажити в ЕБ:регістрі 6 повну адресу Команди пересилання прапорців LAHF LAHF Завантажує прапорці в АЬ SAHF SAHF Встановлює прапорці з АЬ PUSHF PUSHF Поміщає прапорці у стек POPF POPF Виштовхує прапорці зі стека Командою MOV передбачено пересилання байта чи слова з регістра у регістр, з пам’яті в регістр або з регістра у пам’ять. Тип даних (байт чи слово), що пересилаються, визначає регістр, який бере участь в пересиланні. Наприклад: MCV Ах, [Table] ; Пересилання слова з пам’яті в Ах. MOV [Table], Ah ; Пересилання байта з Ah у пам’ять. MOV Ds, Ах ; Завантаження сегменгаого регістра Ds. MOV Es: [Бас], Ах ; Пересилання слова в пам’ять: базове адресування із заміною сегмента. MOV ch,-17 ; Пересилання константа в регістр. За допомогою MOV неможливо: • пересилати з пам’яті в пам’ять. Наприклад, замість команди mcv [Меті], [Мет2] необхідно використовувати дві команди: MOV Ах, [Мего2 ] MOV [Меті] ,Ах . • записати константу або змінну в Ds. Наприклад, замість команди mov ds, [Datajseg] необхідно використовувати дві команди: MOV Ах, [Data_Seg]
366 5.9. Система команд MOV Dsf Ах . • помістити вміст одного сегментного регістра в інший. Наприклад, не можна: mov es,ds , але можна так: MOV Ах, Ds MOV Es,Ax. З метою тимчасового зберігання регістрів і даних, а також з метою обміну значеннями між регістрами широко використовують стекові команди PUSH і POP. Кожна з них працює зі словом, тобто у стек неможливо помістити або витягнути з нього один байт. Під час виконання PUSH спочатку зменшується на 2 вміст вказівника Sp а потім операнд розташовується за адресою Ss:Sp. При витяганні зі стека спочатку читається вміст пам’яті за адресою Ss: Sp, а потім Sp збільшується на 2. Отож, при заповненні вказівник вершини стека Sp зміщується до молодших адрес, а при звільненні - до старших. Під час роботи зі стеком необхідно пам’ятати про специфіку використовування стекової пам’яті (“останнім прийшов - першим вийшов”), а також про те, що ця пам’ять інтенсивно використовується під час виклику процедур, тобто стан стека до моменту виходу з процедури повинен бути строго узгоджений з подальшою роботою програми. Перша умова визначає порядок витягання даних зі стека. Друга умова фактично означає, що після виходу з процедури покажчик Sp повинен містити те ж саме зміщення, що і до моменту входу в неї. Отож, процедура не повинна “забувати” у стеку жодного слова або забирати з нього більше, ніж записала. Команда завантаження адреси LEA завантажує в^ регістр адресу (зміщення) потрібної ділянки пам’яті. Цього ж можна досягти за допомогою зарезервованого слова offset. Наприклад: MOV Ах, [OFFSET X] ; Завантажує зміщення X в Ах. LEA Ах , [X] ; Результат буде той самий. Різниця полягає в тому, що у випадку застосування команди LEA передбачено використання індексної адресації, що передусім зручно при пересиланні масивів даних. Команди завантаження адреси - LDS і LES завантажують перше /6-розрядне слово з джерела в регістр-приймач, а потім наступне слово - в регістр Da або Ез, тобто вони розраховані на завантаження повної адреси операнда (сегмента і зміщення).
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 361 5.9.2. Арифметичні команди Назва команди Формат запису Фущції Команд и додавання ADD ADD приймач, джерело Додає значення джерела і приймача і розташовує суму в приймач ADC ADC приймач, джерело Скласти, додати перенесення INC INC приймач Збільшує вміст приймача на одиницю Команди віднімання SUB SUB приймач, джерело Віднімає значення джерела і приймача і поміщає різницю в приймач SBB SBB приймач, джерело Віднімає із позикою DEC DEC приймач Зменшує вміст приймача на одиницю NEG NEG приймач Змінює знак на протилежний СИР СМР приймач, джерело Порівнює вміст джерела і приймача, встановлюючи відповідний прапорець Команди множення MUZ MUL джерело Перемножує без знака IMUL IMUL джерело Перемножує зі знаком Команди ділення DIV DIV джерело Ділить без знака IDIV IDJV джерело Ділить зі знаком Команди розширення знака CBW CBW Перетворює байт у слово CWD CWD Перетворює слово у подвійне слово
368 5.9. Система команд Під час використання арифметичних команд необхідно пам’ятати, що МП може обробляти числа зі знаком, числа беззнакові, а також двійково-десяткові (BCD) числа. У беззнакових числах з метою представлення значення використовують усі біти, тобто вони еквівалентні типам Byte і Word, тоді як числа зі знаком у старшому розряді містять знак числа. Вони є еквівалентними типам Shortlnt і Integer. Двійково-десяткові числа використовують по 4 біти для кожного десяткового розряду і можуть бути запакованими або незапакованими. У першому випадку один байт містить 2 десяткові цифри (старша - у старшому півбайті), в другому - тільки одну (старший півбайт не використовується). Головні арифметичні команди МП (ADD, SUB, MUL, DIV) не враховують двійково-десяткову форму представлення чисел, отож, архітектура МП налічує команди корекції результату. Приклад. Програма додавання двох цілих чисел. IDEAŁ г програма у форматі Tasm.exe DOSSEG MODEL Small r визначення моделі пам'яті STACK 256 r визначення розміру стека DATASE6 r сегмент даних ExitCode DB 0 Count DW 1 CODESE6 r сегмент коду Start: % MOV Ax, Qdata 7 ініціювання регістру 05 MOV Dsf Ax t для базування ним сегменту данцх MOV Ax, 4 r Ах <— 4 \ MOV Bx, 2 r Вх <- 2 ADD Ax, Ax r Ах 4- Ах + Вх Exit: MOV Ah, 04Ch f функція ООБ для виходу з програми MOV A1, [ExitCode] ; завантаження в AI коду успішного завершення програми (0) INT 21h завершення програми і вихід в операційну систему END Start ; точка завершення програми
5. ЗВ’ЯЗОК PASCAL-AСЕМБЛЕР 369 5.9.3. Побітові команди Назва команди Формат запису Функції Логічні команди AND AND приймач, джерело Виконує AND OR OR приймач, джерело Виконує OR XOR XOR приймач, джерело Виконує XOR NOT NOT приймач Виконує NOT TEST TEST приймач, джерело Виконує логічне порівняння І Команди зсувів SAL/SHL SAL приймач, лічильник Зсуває вліво SAR/SHR SAR приймач, лічильник Зсуває управо ROL ROL приймач, лічильник Зсуває вліво циклічно ROR ROR приймач, лічильник Зсуває управо циклічно RCL RCL приймач, лічильник Зсуває вліво з перенесенням RCR RCR приймач, лічильник Зсуває управо з перенесенням Побітові команди використовують під час обробки логічних виразів, а також у тих випадках, коли необхідно змінити окремі розряди операнда. Логічні команди AND, OR, XOR і NOT еквівалентні відповідним операціям середовища ВР у разі, коли операндами є ціло-чисельні вирази. Команда TEST виконує цілочисельну операцію порозрядного додавання AND, проте не змінює значення операндів, а лише встановлює прапорці відповідно до значення результату порівняння: занулює CF і змінює PF, ZF, SF, проте не змінює AF (прапорець zf встановиться в 1 у тому випадку, коли обидва операнди містять по одиниці хоча б в одному відповідному розряді). Команди зсуву SHL/SHR еквівалентні однойменним операціям середовища ВР і відрізняються від команд
370 5.9. Система команд циклічного зсуву ROL і ROR тим, що витіснені під час їхнього виконання значущі розряди втрачаються, а під час циклічного зсуву ці розряди з’являються “з іншого боку”. Наприклад, якщо виконати фрагмент: MOV А1,1 ; Завантаження в А1 одиниці SHR А1,1 ; Зсув праворуч вмісту АІ на 1 розряд, то регістр А1 міститиме 0 (витіснену вправо одиницю буде розташовано в CF); після заміни команди SHR на ROR в AL буде значення $80 = 128 (витіснену одиницю буде розташовано у старшому біті регістра). Зазначимо, що лічильником у командах зсуву може слугувати цифра 1 або кількість зсувів, зазначена у регістрі сх. 5.9.4. Команди передачі управління Назва команди Формат запису Функції Безумовні переходи CALL CALL ім’я Викликає процедуру RET RET [кількість параметрів] Повертає управління з процедури JMP JMP мітка Передає управління на мітку Умовні переходи JA/JIЯВЕ JA ближнямітка Перехід, якщо вище (після порівняння беззнакових \ операндів) \ . \ JAE/JNB ^ JAE ближня_мітка Перехід, якщо вище або дорівнює JB/JBAE/JC JB ближня_мітка Перехід, якщо нижче JBE/JNA JBE ближня_мітка Перехід, якщо нижче або дорівнює JCXZ JCXZ ближня_мітка Перехід, якщо вміст Сх= 0 JE/JZ JE ближня_мітка Перехід, якщо рівно або нуль JG/JNLE JG ближня_мітка Перехід, якщо більше (після порівняння знакових операндів)
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 371 Назва команди Формат запису Функції JGE/JNL JGE ближня_мітка Перехід, якщо більше або дорівнює JL/JNGE JL ближня_мітка Перехід, якщо менше JLE/JNG JLE ближня_мітка Перехід, якщо менше або дорівнює JNC JNC ближня_мітка Перехід, якщо немає перенесення JNE/JNZ JNE ближня_мітка Перехід, якщо не дорівнює або, якщо не нуль JNO JNO ближня_мітка Перехід, якщо немає переповнення JNP/ JPO JNP ближня_мітка Перехід, якщо непарний JO JO ближня_мітка Перехід, якщо є переповнення JP/JPE JP ближня_мітка Перехід, якщо парний JS JS ближня_мітка Перехід, якщо негативний Команди управління циклами LOOP LOOP ближня_мітка Виконує цикл LOOPE/LOOPZ LOOPE ближня_мітка Повторює, доки дорівнює LOOPNE/LOOPNZ LOOPNE ближня_мітка Повторює, доки не дорівнює Команди безумовних переходів CALL, RET, JMP можуть використовувати дальню або ближню модель пам’яті, водночас команди умовних переходів - тільки ближню (в межах -128..+127 байт). За дальньої моделі пам’яті (яка встановлюється опцією Options\Compilet\Force far calls середовища BP або директивою
372 5.9. Система команд компілятора {$F+}) здійснюється як внутрішньосегментна, так і міжсегментна передача управління, при ближній - тільки внутрішньосегментна. Опишемо алгоритм роботи команди CALL. Спочатку адреса наступної за CALL команди (адреса повернення) надходить у стек, потім у регістр ір (або в пару Сз:ір) надсилається адреса точки входу в процедуру, тобто відразу за командою CALL виконуватиметься перша команда процедури. Обидві адреси (точки входу і повернення) будуть 16- бітовими зсувами для внутрішньо- сегментного виклику або 52-бітовими повними адресами - для міжсегментного. Усі процедури (функції) мови Pascal, компільовані в режимі {$F+} або такі, що містять зарезервоване слово Far у заголовку, необхідно викликати як дальні. З цією метою разом з командою CALL необхідно зазначити модель пам’яті. Наприклад: Procedure MyProc; Far; Asm CALL Far MyProc {Виклик дальньої процедури} End; Подібним способом викликають усі бібліотечні підпрограми (тобто оголошені в інтерфейсних частинах модулів). За віддаленого виклику в стек спочатку записується вміст регістра сегмента коду Cs, а вже потім - зсув точки повернення. Під час виходу з дальньої процедури команда RET витягує зі стека обидва 16-розрядні слова і розташовує перше в ір, а^друге в Cs, а під час виходу з ближньої - витягує зі стека тільки зсув і розташовує його в ір. Команді умовних переходів здатні передавати управління на мітку, розташовану в межах найближчих ±128 байт від самої команди. Якщо необхідно передати управління на мітку, розташовану далі у тому самому сегменті, або на мітку в іншому сегменті, відразу за командою умовної передачі розташовують безумовну команду JMP або CALL. Наприклад. СТР Ах, 0 ; перевіряємо Ах JNE @NotZero ; умовний перехід, якщо вміст Ах * 0 JMP I sZero ; переходимо на дальню мітку, якщо вміст Ах = 0 ; якщо ні - продовжуємо роботу
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 373 У таблиці термін “вшце/нижче” використовують стосовно порівняння беззнакових операндів, а “більше/менше” - знакових. Оскільки умовні переходи реалізують розгалуження програми на підставі перевірки прапорців, зазвичай, безпосередньо перед ними розташовуються команди, які можуть змінювати ці прапорці. Найчастіше - - це команда порівняння СМР. Нижче подано комбінації “СМР-умовний_перехід” для різних співвідношень приймача і джерела (першого і другого операнда) команди СМР. Умова Для беззнакових чисел Для чисел із знаками Приймач більший від джерела JA JG Приймач і джерело ідентичні JE JE Приймач менший джерела JB JL Приймач не менший джерела JAE JGE Приймач не більший джерела JBE JItE Приймач і джерело ідентичні ЛЯЕ JNE Наприклад. СМР Ах, 5 ; порівняння вмісту Ах з числом 5 JA QAboveS ; якщо більше - перехід СТР Вх, -3 ; порівняння вмісту Вх з числом -З JLE @ Le s sM3 ; якщо менше або дорівнює - перехід. Команди LOOP, LOOPE, LOOPNE слугують для організації циклів. Усі вони використовують вміст регістра Сх як лічильник числа повторень. Команда LOOP зменшує Сх на одиницю і передає управління на мітку початку циклу, якщо вміст цього регістра не дорівнює нулю. Команди LOOPE і LOOPNE також зменшують лічильник Сх, проте передають управління на початок циклу за одночасної умови встановлення (або скидання) прапорця ZF і за умови, що вміст лічильника Сх не дорівнює нулю.
374 5.9. Система команд Приклад, що демонструє, як можна відшукати нульовий байт в масиві АОВ: Var AOB: Array [1..1000] of Byte; Asm MOV Cx, 1000 {Ініціюємо лічильник Cx] LEA Bx, AOB {Поміщаємо адресу AOB у регістр' Bx} DEC Вх {Готуємо цикл} {Початок циклу перевірки} @@Test: INC Вх {Адреса чергового байта} СМР [Byte Ptr Вх], 0 {Перевіряємо байт} LOOPNE @@Test {Замикаємо цикл} JNZ QNotZero {Якщо не знайдений нульовий байт} {Знайшли нульовий байт} End; 5.9.5. Рядкові команди Назва команди Формат запису Функції Пересилання рядків MOVSB MOVSB Пересилає байти MÖVSW MOVSW Пересилає слова Порівняння рядків CMPSB CMP SB Порівнює байти CMPSW CMPSW Порівнює словах Сканування SCASB ь SCASB Шукає байт SCASW SCASW Шукає слово Завантаження і збереження LODSB LODSB Завантажує байти LODSW LODSW Завантажує слова STOSB STOSB Зберігає байти STOSW STOSW Зберігає слова
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 375 Рядкові команди розраховані на обробку рядків. Термін “рядок” тут зовсім не еквівалентний аналогічному терміну мови Pascal і означає довільний ланцюжок байтів або слів завдовжки до 64Кб. Ці команди оперують п’ятьма примітивами, кожен з яких обробляє лише один байт або одне слово за раз. Перед примітивом, зазвичай, указується префікс повторення REP, REPE, REPNE, що примушує виконуватися примітив доти, доки лічильник повторень Сх не дорівнюватиме нулю або не буде порушено відповідну умову. Під час використовування рядкових команд важливо пам’ятати дві обставини. По-перше, ці команди завжди беруть адресу рядка-джерела з пари Vs: Si, а рядка-приймача - з пари Es: Di. Отже, перед виконанням рядкової команди необхідно заповнити сегментні регістри потрібним способом. По-друге, рядкові команди використовують індексну адресацію з автоматичною зміною зсуву в si або Di після однократного виконання примітиву. Вміст цих регістрів змінюється на 1 за обробки байтів і на 2 за обробки слів, причому вміст нарощується, якщо прапорець напряму DF скинуто, і зменшується, якщо він дорівнює 1. Приклад. Пересилання масиву А в масив В: Var А, В: Array [1..250] of Integer; Asm LEA Si, А {Зсув A - в Si (джерело)’} PUSH Ds POP Es {Заповнюємо: Es := Ds) LEA Di, В {Зсув В - в Di (приймач) } MOV Ex, 250 {Лічильник- перенесення} CLD {Напрям перенесення - нарощувати} Rep MDVSW {Перенесення 500 байт} End; У Pascal-програмі регістр Ds завжди містить адресу сегмента даних, отож, ініціювати його не обов’язково. Що стосується регістра додаткового сегмента Es, такого правила не існує. Хоча, здебільшого, він також посилається на сегмент даних, рекомендується здійснювати його заповнення перед застосуванням рядкової команди (див. вище команди push Ds, pop Es).
376 5.9. Система команд 5.9.6. Система переривань Переривання - це тимчасова зупинка працюючої програми з метою запуску спеціальної підпрограми обробки переривань, у разі виникнення позаштатної чи збійної ситуації. Підпрограма може виконувати сервісні дії, обслуговувати запити користувача або реагувати на аварійні ситуації. Підпрограму, що активізується у цьому випадку, називають ISR (Interrupt Service Routine). Intel- сумісний МП розрізняє 2 види переривань: зовнішні та внутрішні. Зовнішні переривання - це переривання від периферійних пристроїв, які сигналізують МП про те, що необхідне його втручання для обробки певної події. Внутрішні переривання відбуваються у випадку виникнення збійних ситуацій під час виконання прикладної програми, наприклад, при переповненні розрядної сітки або під час спроби ділення на нуль. Механізм переривань підтримується на апаратному рівні і дає змогу реалізувати як ефективну взаємодію програми з ОС, так і програмне управління апаратною частиною комп’ютера. Залежно від джерела переривання, останні класифікують так: • Апаратні, що виникають як реакція мікропроцесора на фізичний сигнал від деякого пристрою комп’ютера (клавіатури, системного таймера, жорсткого диска і т. д.). За часом свого виникнення ці переривання є асинхронними, тобто такими, що трапляються у випадкові моменти часу. • Програмні, що активізуються штучно з допомогою відповідної команди з програми. Вони призначені для виконання певних дій ОС. Ці переривання є синхронними. • Винятки - різновид програмних переривань, які проявляються як реакція МП на нестандартну ситуацію, що виникла всередині МП під час виконання деякої команди програми. Існує три команди переривань. Розглянемо їхню роботу. Першою командою є: • int < номер> - виконати переривання. Виконання переривань багато в чому нагадує непрямий виклик дальньої процедури. За командою INT у стек потрапляє
5. ЗВ’ЯЗОК PASCAL-ЛСЕМБЛЕР 377 вміст регістра прапорців, вміст сегментного регістра Сз і вказівника ір. Нові значення цих регістрів записують із ¥-байтного вектора переривання, що відповідає <номеру> переривання - операнда команди INT. • into - виконати переривання за переповненням. Команда INTO є умовним перериванням і виконується, якщо на цей момент встановлено прапорець переповнення. Механізм роботи цієї команди подібний до попередньої, проте нові значення регістрів беруть із вектора 4. Отже, команди INT та INTO відрізняються від команди CALL тим, що у стек заздалегідь заноситься регістр прапорців. Зауважимо, що перед наданням управління програмі обробки переривання МП скидає прапорці трасування TF і переривань IF. Скидання значення TF необхідне для забезпечення нормальної роботи налагоджувачів, що використовують переривання за вектором 1 або 4. Скидання значення IF блокує втручання інших процесів у виконання обробки переривання. • IRET - повернення з 7Ж/?-процедури. Команда IRET реалізує правильний вихід з програми обробки переривання: вона читає зі стека З двобайгові слова і розташовує їх, відповідно, у регістри ip, Сз і регістр прапорців. Система переривань роботи комп’ютера дає змогу МП швидко реагувати на події, обробку яких необхідно виконати негайно: сигнали від машинних таймерів, натиснення клавіш клавіатури або миші, збої пам’яті та ін. Сигнали апаратних переривань, які виникають у пристроях, що належать до системного блоку комп’ютера або підключених до нього через порти, надходять у процесор не безпосередньо, а через два контролери переривань, один з яких є головним, а другий - підлеглим. Два контролери використовують з метою збільшення допустимої кількості зовнішніх пристроїв, адже кожен контролер переривань може обслуговувати сигнали лише від 8-ми пристроїв. Для обслуговування більшої кількості пристроїв контролери можна об’єднувати, утворюючи з них віялоподібну структуру. У сучасних машинах встановлюють два контролери, збільшуючи тим самим можливе число вхідних пристроїв до 75-ти (7-у головного і 8 - у підлеглого контролерів). До вхідних контактів контролера, що
378 5.9. Система команд називають IRQL.IRQ7 і IRQ8..IRQ15 (IRQ - це скорочення від Interrupt Request, запит переривання) під’єднують виводи пристроїв, на яких виникають сигнали переривань. Вихід головного контролера під’єднують до входу INT мікропроцесора, а вихід підлеглого - до входу IRQ2 головного. Головна функція контролерів - передача сигналів запитів переривань від зовнішніх пристроїв на єдиний вхід переривань МП. У цьому випадку, окрім сигналу INT.контролери передають у МП лініями даних номер вектора, який утворюється в контролері шляхом складання базового номера, записаного в одному з його регістрів, з номером вхідної лінії, якою надійшов запит переривання. Номери базових векторів заносять у контролери автоматично в процесі початкового завантаження комп’ютера. Для головного контролера базовий вектор завжди становить 8h, для підлеглого - 70h. Отже, номери векторів, закріплених за апаратними перериваннями, перебувають в діапазонах 8h. .Th і 7 Oh.. 7 7h. Очевидно, що номери векторів апаратних переривань однозначно взаємозв’язані з номерами ліній, або рівнями IRQ, а через них - з конкретними пристроями комп’ютера. Процесор, одержуючи сигнал переривання, виконує послідовність стандартних дій, яку називають процедурою переривання. Зауважимо, що тут йдеться лише про реакцію самого процесора на сигнали переривань, а не про алгоритми обробки переривань, передбачені користувачем у програмах обробки переривань. Початок ОП від адреси 0000h до 03FFh відводиться під вектори переривань - чотирибайтові області, в яких зберігаються адреси обробників переривань. У два старші байти кожного вектора записується сегментна адреса обробника, у два молодші - зміщення (відносна адреса) точки входу в обробник. Вектори, як і відповідні щодо них переривання, мають номери, причому вектор з номером 0 розташовується, розпочинаючи з адреси 0000h, вектор / - з адреси 0004h, вектор 2-з адреси 0008h і т.д. Вектор з номером N займає, відповідно, байти пам’яті від N*4 до N*4+3. Загалом у виокремленій під вектори області пам’яті вміщається 256 векторів. Одержуючи сигнал на виконання процедури переривання з певним номером, процесор зберігає у стеку виконуваної програми поточний вміст трьох регістрів процесора: регістра прапорців, Сз та ір. Два останні числа утворюють вичерпну адресу точки повернення у перервану програму. Далі процесор завантажує вміст
5. ЗВ ЯЗОК PASCAL-AСЕМБЛЕР 379 Сз і ір з відповідного вектора переривань, здійснюючи тим самим перехід на обробник переривання, взаємозв’язаний з цим вектором. Обробник переривань завжди завершується командою LRET (Interrupt Return - повернення з- * переривання), яка виконує зворотну дію - добування зі стека збережених там слів та їхній запис назад у регістри ір та Cs, а також в регістр прапорців. Така процедура забезпечує повернення до тієї самої точки головної програми, у якій трапилось переривання. Насправді існують різноманітні запити на обробку переривань. Окрім описаних вище апаратних переривань від периферійних пристроїв, які називають часто зовнішніми, є ще два типи переривань: внутрішні і програмні. Внутрішні переривання збуджуються підсистемами самого процесора за виникнення однієї зі спеціально зумовлених ситуацій (наприклад, під час спроби виконати операцію ділення на нуль або під час спроби виконати неіснуючу команду). За кожним з таких переривань закріплено певний вектор, номер якого відомий процесору. Наприклад, за діленням на 0 закріплено вектор 0, а за неправильною командою - вектор 6. Якщо виникає одна із нештатних ситуацій, процесор виконує описану вище процедуру переривання, використовуючи закріплений за цією ситуацією вектор переривання. Зрештою, існує ще один важливий тип переривання - переривання програмне. Його активізує команда INT з числовим аргументом, який розглядається процесором як номер вектора переривання. Якщо в програмі трапляється, наприклад, команда int 13h, то процесор виконує процедуру переривання, вважаючи номером вектора операнд команди INT. Програмні переривання застосовують, передусім, для виклику системних обслуговуючих програм - функцій DOS і BIOS. Команда int 21h передає управління ОС. Нижче наведемо приклади використовування команди INT для виклику прикладних обробників програмних переривань. Зауважимо, що описані дії процесора виконуються абсолютно однаково для всіх видів переривань - внутрішніх, апаратних і програмних, хоча причини, що збуджують процедуру переривання, мають принципово різну природу. Більшість векторів переривань зарезервована для виконання певних дій; деякі з них автоматично заповнюються адресами системних програм при завантаженні ОС.
380 5.9. Система команд Наведемо, для прикладу, частину векторів переривань: Таблиця 5.1 Деякі вектори переривань Номер Функції ООЬ Внутрішнє переривання типу ділення на 0 ОІЬ Внутрішнє переривання для покрокового виконання програми 02Ь Немасковане переривання (виведення М// процесора) 081і Апаратне переривання від системного таймера ( 09Ь Апаратне переривання від клавіатури ОЕЬ Апаратне переривання від гнучкого диска ЮЬ Програмне переривання, програми ВІОБ управління ІЗЬ Програмне переривання, програми ВІ08 управління дисками 16Ь Програмне переривання, програми ВІ08 управління 1Х)Ь Адреса таблиці відеопараметрів, що використовує ВІ08 ГЕЬ. Адреса таблиці параметрів дискети, що використовує ВЮ$ 21Ь Програмне переривання, диспетчер функцій ИОБ 22Ь Програмне переривання, адреса переходу за умови завершення 23Ь Обробник програмного переривання по |Сґ/7+С| 25Ь Програмне переривання, читання диска (функція В08) 2вЪ. Програмне переривання, запис на диск (функція БОЯ) 60Ь..66Ъ Зарезервовано для програмних переривань користувача 68Ь. . віЬ. Програмні переривання, вільні вектори 76Ь ► Апаратне переривання від жорсткого диска \ Як бачимо з табл. 5.1, вектори переривань можна умовно розбити на такі групи: • Вектори внутрішніх переривань процесора (ОІЬ, 021і та ін.). • Вектори апаратних переривань (08Ь.. Оіть і 70Ь.. 77Ь). • Програми ВЮ8 обслуговування апаратури комп’ютера (ЮЬ, ІЗЬ, ІбЬтаін). • Програми 2)05 (21Ь, 22Ь, 23Ь та ін.). • Адреси системних таблиць ВІ08 (ІБЬ, іЕЬтаін.).
5. ЗВ’ЯЗОК PASCAL-АСЕМБЛЕР 381 Системні програми, адреси яких зберігаються у векторах переривань, здебільшого слугують лише диспетчерами, що відкривають доступ до великих груп програм, які реалізовують системні функції. Наприклад, відеодрайвер BIOS (вектор lOh) налічує програми зміни відеорежиму, управління курсором, задання палітри кольорів, завантаження шрифтів і багато інших. Вирізняється щодо цього вектор 2lh, завдяки якому відбувається виклик практично всіх функцій DOS: введення з клавіатури і виведення на екран, обслуговування файлів, каталогів і дисків, управління пам’яттю і процесами, служби часу і т. д. З метою активізації певної функції необхідно не тільки виконати команду INT з відповідним номером, але й задати системі в регістрі Ah номер функції, що викликається. Іноді для “багатофункціональних” функцій доводиться задавати ще і номер підфункції у регістрі А1. 5. 9.7. Команди управління Мнемоніка Формат Коментар Управління прапорцями STC STC Встановити перенесення CLC CLC Зняти перенесення CMC CMC Інвертувати СЕ STD STD Задати напрям CLD CLD Зняти напрям STI STI Дозволити переривання CLI CLI Заборонити переривання Зовнішня синхронізація HLT HLT Зупинити обчислення WAIT WAIT Чекати активності на шині ESC ESC код, джерело Передати команду LOCK LOCK Захопити шину Порожня команда NOP NOP Немає операції
382 5.9. Система команд Опишемо роботу команд зовнішньої синхронізації. HLT переводить МП у стан зупинки, з якого його можна вивести тільки за умови перезавантаження ОС або за умови виникнення немаскованого переривання. WAIT примушує МП виконувати холостий режим роботи і кожні 5 тактів перевіряти рівень сигналу на вхідній шині: доки на цій шині немає сигналу активності, процесор виконує WAIT, проте за умови активізації він продовжить виконання програми. Цю команду, зазвичай, використовують для очікування сигналу обслуговування (переривання) високопріоритетного пристрою типу контролера прямого доступу до пам’яті. Команду ESC застосовують для передачі зазначеного у ній операнда на шину даних. Так забезпечується можливість передачі команд іншим процесорам. Цю команду найчастіше використовують для управління роботою арифметичного копроцесора. У цьому випадку код є кодом команди копроцесора, а джерелом у цій команді слугує операнд. Команда LOCK фактично є однобайтовим префіксом, який можна використовувати спільно з будь-якою іншою командою МП. За цією командор МП активізує однойменний сигнал на своїй шині, що унеможливлює використання цієї шини будь-яким іншим зовнішнім пристроєм (процесором).
5. ЗВ’ЯЗОК PASCAL-ЛСЕМБЛЕР 383 5.10. Математичний копроцесор 5.10.1. Типи даних Копроцесор обробляє три формати чисел із плаваючою комою: одинарної точності, подвійної точності, розширеної точності. Ці числа ще називають, відповідно: коротким дійсним, подвійним дійсним і розширеним дійсним (рис. 5.11). У мові Pascal це такі типи даних: Single, Double і Extentded. Нагадаємо, що ці типи даних забезпечують точність 7, 15 і 19 знаків після коми. 79 64 0 розширене 63 52 порядок мантиса подвійне 31 22 поря¬ док мантиса коротке Рис. 5.11. Формата чисел із плаваючою комою Кожне число цих форматів містить три поля: знак числа, його порядок і мантиса. В оперативній пам’яті, залежно від формату, ці числа займають, відповідно, 4, 8 і 10 байт. Байт із найменшою адресою є наймолодшим байтом мантиси, наступними є більш значущі байти мантиси, за ними розташовані байти порядку від наймолодшого до найстаршого. Останній байт числа містить 7 біт порядку та однобітне поле знака числа. Тобто старші значущі цифри як мантиси, так і порядку мають вищі адреси. Нуль (0) у знаковому біті означає, що число додатне, 1 - від’ємне. Зі зміною знака числа змінюється вміст тільки цього біта. На відміну від цілих чисел доповняльний код тут не використовують. Нуль дійсного типу містить усі нулі як в полі мантиси, так і в полі порядку. Тобто існує 2 типи нуля: +0 і -0. Проте у командах порівняння обидва нулі вважають одним числом. Отож, під час використання для порівняння двох дійсних чисел цілочисельної команди СМР можна отримати помилковий результат.
384 5.10. Математичний ^сопроцесор Окрім двох типів нуля під час виконання математичних операцій можуть виникнути такі спеціальні ситуації. • Додатна оо : знаковий біт містить 0; всі біти мантиси - 0; всі біти порядку - 1. • Від9ємна оо : знаковий біт містить /; всі біти мантиси - 0; всі біти порядку - 1. • Денормалізоване число: всі біти порядку - 0. Ви¬ користовується для роботи з дуже малими числами - до Ю'16445 для випадку розширеної точності. ( • Невизначеність: знаковий біт містить 1; перший біт мантиси (перші 2 для 50-бітових чисел) - і; решта - 0; всі біти порядку 1. • He-число типу SNAN (сигнальне): всі біти експоненти - 1\ перший біт мантиси - 0 (для 50-бітових чисел перші 2 біти мантиси 10); серед інших бітів є одиниці. • He-число типу QNAN (тихе): всі біти експоненти - 1; перший біт мантиси - 0 (перші 2 для 50-бітових чисел); серед інших бітів є одиниці; оо - один із варіантів QNAN. • Число, яке не підтримується: всі інші ситуації. З метою отримання найвищої точності мантису нормалізують: порядок числа змінюють так, щоб найстарший (лівий) біт мантиси не був нульовим. Поле порядку визначає степінь числа 2, на яку потрібно помножити мантису, щоб отримати зазначене число з плаваючою комою. Щоб ^опрацьовувати числа із від’ємними порядками в полі порядку постійно знаходиться не справжній порядок числа, а сума цього порядку і деякої додатної константи - так званого зміщення. Для типу Single значення цієї константи становить /27, для Double - 1023, а для Extended -16 383. Наприклад, якщо порядок числа типу Single становить 5, то поле порядку міститиме 127+5=132, зазвичай, у 2-му представленні. Якщо ж порядок -5, то у полі порядку буде значення 127-5= 122. Пояснити вибір константи 127 для одинарної точності можна так. Оскільки у форматі з одинарною точністю довжина порядку становить 8 бітів, то 28-1 = 255, тоді найбільший справжній порядок становитиме 255-127=128, а найменший - 0-127=* -127. Тобто збільшення порядку найменшого дійсного числа одинарної точності на 127 спричинить до зникнення від’ємного порядку у
5. ЗВ'ЯЗОК PASCAL-ACEMEJIEP 385 його машинному представленні. Зекономлений у такий спосіб біт додається до бітів мантиси, що підвищує точність представлення чисел у цьому форматі. 5.10.2. Регістри копроцесора Копроцесор містить 13 власних регістрів: • 8 50-розрядних регістрів FPU (Floatin Point Unit) зі стековою формою організації; • 5 службових регістрів, з яких регістри Cr, Sr i Tw є /б-розрядні, Fip і Fdp - ^5-розрядні. Регістри FPU об’єднані у стек, вершину якого називають ST або ST (0). Нижні елементи називають, відповідно, ST(1), ST(2),..., ST(7). Під час запису чисел в регістри вершина стека може рухатись вниз чи вгору. Це означає, що після запису нового числа у стек число, яке до того перебувало в ST(0), переміститься в ST (1). Відповідно, свої адреси змінять усі інші числа, які у цей момент записані в регістри. Таку особливість треба постійно враховувати під час написання на Асемблері програми для обробки чисел з плаваючою комою. 5.10.3. Команди копроцесора Перші 5 бітів кожної команди FPU містять 11011, що сигналізує цілочисельному блокові процесора: це не його команда. Назва кожної команди розпочинається з символу F. Для адресування даних можна застосовувати ті ж види адресувань, що й для команд обробки цілих чисел. Команди переміщення даних Назва команди Формат запису Функції FLD FLD джерело Завантажує дійсне число у вершину стека FST FST приймач Копіює дісне число із вершини стека у приймач FSTP FSTP приймач Виштовхує дісне число із вершини стека у приймач 13 7-451
386 5.10. Математичний копроцёсор Назва команди Формат запису Функції FILD FILD джерело Завантажує ціле число у вершину стека. FIST FIST приймач Копіює ціле число із вершини стека у приймач FISTP FISTP приймач Виштовхує ціле число із вершини стека у приймач FBLD FBLD джерело Завантажує десяткове число у вершцру стека FBSTP FBSTP приймач Виштовхує десяткове число із вершини стека у приймач FXCH FXCH джерело Обмін вмісту вершини стека і регістра- джерела Трансцендентні команди Назва команди Формат запису Функції FSIN FSIN Обчислює в радіанах синус числа, яке перебуває в БЬ (0) \ записує туди ж результат FCOS FCOS Обчислює в радіанах косинус числа, яке перебуває в БЬ (0); записує туди ж результат FPTAN FPTAN Обчислює в радіанах косинус числа, яке перебуває в 8Ь (0); записує в ^ (0) одиницю, а результат - в FPATAN FPATAN Обчислює арктангенс числа, же отримується під час ділення БЬ (1) на ^ (0); записує результат в^: (1) і виштовхує БЬ (0) зі стека
5. ЗВ’ЯЗОК РА8САЬ-АСЕМБЛЕР 387 Команди завантаження констант у стек Назва команди Формат запису Функції ГІЯО ЕІЯО Завантажує у стек +0.0 ЕІВІ ЕІВІ Завантажує у стек 1.0 ГХСРІ пиві Завантажує у стек я ПОі2Е ЕЫ)12Е Завантажує у стек ^2(е) ЕЫ)12Т ЕІВІ2Т Завантажує у стек ^2(10) РЫ)Ш2 ЕІИШ2 Завантажує у стек 1п(2) ГІВЬЄ2 ЕЫ)1&2 Завантажує у стек Ц*(2) Арифметичні команди Назва команди Формат запису Функції Додавання ЕАВИ приймач,джерело Додає два дійсних числа ЕАЛИР ЕАОБР приймач,джерело Додає два дійсних числа, виштовхуючи вміст БЬ (0) зі стека ЕІЛЛИ ГІШШ приймач,джерело Додає два цілих числа Віднімання гвив ЕБЦВ приймач,джерело Віднімає два дійсних числа ЕвУВР ЕБХШР приймач,джерело Віднімає два дійсних числа, виштовхуючи вміст БЬ (0) зі стека ЕІвиВ п&ив приймач,джерело Віднімає два цілих числа ЕвЦВЯ ТБітя приймач,джерело Віднімає два дійсних числа в оберненому порядку: приймач від джерела
388 5.10. Математичний копроцесор Назва команди Формат запису Функції ЕБиВРР ЕБиВКР приймач,джерело Віднімає в оберненому порядку два дійсних числа, виштовхуючи вміст 5^ (0) зі стека гіБивя ГІ5СШК приймач,джерело Віднімає в оберненому порядку два цілих числа Множення , шиї тмиь приймач,джерело Множить два дійсних числа шиїр тпьв приймач,джерело Множить два дійсних числа, виштовхуючи вміст БЬ (0) зі стека ЕІМиЕ ЕІМиЬ приймач,джерело Множить два цілих числа Ділення ГЯІУ ГВІУ приймач,джерело Ділить два дійсних числа П)Т\ҐР ЕТ)ІУР приймач,джерело Ділить два дійсних числа, виштовхуючи вміст БЬ (0) зі стека ГІИІУ ЕЮІУ приймач,джерело Ділить два цілих числа ІПОІУР. тлтш приймач,джерело Ділить в оберненому порядку два дійсних числа ГОІЮТ ГОІУКР •-приймач, джерело Ділить в оберненому порядку два дійсних числа, виштовхуючи вміст БЬ (0) зі стека ГJDIVR пяіта приймач,джерело Ділить в оберненому порядку два цілих числа ІТКЕМ ЕРВЕМ Ділить БЬ (0) на БЬ (1) і записує залишок від ділення в БЬ (0)
5. ЗВ’ЯЗОК РАБСАЬ-АСЕМБЛЕР 389 Алгебричні команди Назва команди Формат Функції ЕАВБ ЕАВБ Знаходитиме дуль дійсного числа, розташованого в Б€ (0). Результат записує в БЬ (0) ЕСНБ ЕСНБ Змінює на протилежний знак дійсного числа, розташованого в БЬ (0). Результат записує в ВЬ (0) шгоот ЕРІЮШТ Заокруглює значення дійсного числа, розташованого в БЬ (0). ЕБОЯТ ЕБОЯТ Знаходить корінь квадратний дійсного числа, розташованого в БЬ (0). Результат записує в БЬ (0) Команди порівняння Назва Формат Функції ЕСОМ ЕСОМ джерело Порівнює вміст БЬ (0) з джерелом і встановлює відповідні значення прапорців СО, С2, СЗ ЕСОМР ЕСОМР джерело Порівнює вміст БЬ (0) з джерелом, встановлює відповідні значення прапорців СО, С2, СЗ і виштовхує вміст БЬ(О) зі стека ЕСОМРР ЕСОМРР джерело Порівнює вміст БЬ (0) з джерелом, встановлює відповідні значення прапорців СО ,С2 ,СЗ і виштовхує вміст БЬ (0) і БЬ (1) зі стека ПСОМ ЕІСОМ джерело Порівнює цілочисельний вміст БЬ (0) 3 цілочисельним джерелом і встановлює відповідні значення прапорців СО, С2, СЗ ЕІСОМР ЕІСОМР джерело Порівнює цілочисельний вміст БЬ (0) з джерелом, встановлює відповідні значення прапорців СО, С2, СЗ і виштовхує вміст БЬ (0) зі стека ЕТБТ ЕТБТ Перевіряє чи містить 0 регістр БТ (0) і встановлює відповідні значення прапорців СО, С2, СЗ ЕХАМ ЕХАМ Перевіряє вміст регістра БТ (0) і встановлює відповідні значення прапорців СО, С2, СЗ
390 5.11. Вставка в РлусяЛ-програму фрагментів на Асемблері 5.11. Вставка в Pascal-прогрвму фрагментів на Асемблері Існує 5 варіантів виклику асемблерних фрагментів з програми, що написана мовою Borland Pascal. 1. У будь-якому місці виконуваної частини Л/5са/-програми чи підпрограми пишемо ключове слово Asm, далі задаємо асемблерний код. Фрагмент закінчуємо, ставимо End,. Якщо фрагмент перебуває в тілі функції, результат її роботи заноситься не в змінну - ім’я функції, а у спеціальну змінну @Result, яку описувати не потрібно. Для програмування переходів і циклів використовують мітки, описані у розділі Label. Якщо мітка розпочинається символом @, її описувати не потрібно. 2. Якщо загалом тіло функції складається з одних команд Асемблера, використовують директиву Assembler, яку записують після заголовка функції. У цьому випадку змінну @Result не використовують. Результат заноситься в ім’я функції автоматично з регістра Ах для /б-розрядних значень, з АІ - для S-розрядних і з пари регістрів JDx, Ах - для 52-розрядних. Результат дійсного типу Single беруть із трійки регістрів Dx, Вх, Ах. Результат типу Extended і Double читають із регістра копроцесора St (0). Адреси змінних компілятор бере зі списку формальних параметрів. 3. Директива компілятора {$L <ім'я>] дає змогу вставити у Pascal-програму процедуру або функцію у проасембльованому вигляді, тобто obj-файла: <імуя>.оЬ]. Код вставляється у точку розміщення директиви {$L . У цьому випадку безпосередньо після цієї директиви необхідно записати у форматі ВР заголовок процедури, який закінчується директивою External;. 4. Оператор Inline дає змогу вставляти у Ря$ш/-програму невеликі фрагменти шістнадцяткового коду як набір команд МП. Кожну команду розділяють символом Якщо цей код становить тіло функції, то передавання результатів її роботи програмують так: Asm MOV SResult, Аж . Примітка. Раціональним способом отримання двійкових машинних кодів є написання потрібного фрагмента коду спочатку на Асемблері, запуск програми Turbo Debugger і копіювання необхідних байтів в оператор Inline.
5. ЗВ’ЯЗОК PASC AL-А СЕМБЛЕР 391 5. Директива Inline подібна до оператора Inline, однак тут відсутні команди повернення управління. Результат роботи передається через регістр Ах. Приклади: 1. Програма вводить символи у верхньому регістрі (за натиснутої клавіші CapsLock), а потім, за допомогою функції на Асемблері, переводить ці символи у нижній регістр і виводить їх на текстовий екран. Program Pas_Asm_Demo ; Uses Crt; Var S : String; і : Integer; Tex : Byte Absolute S; Function LC (C: Char) : Char; Assembler; Asm Mov Al, С Mov Bx, 5A41h Спар A1, B1 Jb QCNotUp Cmp Alt Bh Ja QCNotUp Add Al, 32 Лпр @Chcont @CNotUp Cmp Al,08Oh Jb QChcont Cmp Al, 08Fh Ja QRcont Add Al, 32 Jmp QChcont QRcont: Cmp Al, OAOh Jae QChcont Add Al, 80 QChcont : End; BEGIN ClrScr; Repeat Writeln ('Введіть Enter для виходу або ’); Write (’Введіть символи у CapsLock —> '); Readln (S); For i:=l to Tex do Writeln (1 Переведений символ >',LC (S [i])), Writeln; Until Tex = 0 END.
392 5.11. Вставка в Pascal-програму фрагментів на Асемблері 2. Програма, яка виводить на середину текстового екрана IVAN о LEKS. Набираємо її текстовим редактором і записуємо у файл хіоі. asm. Оскільки вона оформлена, як com-файл Ті асемблювати і лінкувати слід тільки так: > Tasm /ш /L ХІОІ. asm > Tlink /t /х XIOl.obj Після запуску на виконання результуючої програми хюі. com вийти з неї можна, натискаючи клавішу “Пробіл” Assume CS: Code, DS: Code Code SEGMENT ORG 100h Start: MOV ax, cs MOV ds, ax ; Встановлення відеорежиму 03 MOV ah, 0 ; функція 0 MOV al, 3 ; режим 3 Int 10h ; Виведення тексту MOV ah, 9 ; функція 9 LEJA dx, text ; зміщення тексту (DS) Int 21h ; Очікування натискання клавіші “Пробіл” loopl: MOV ah, 7 ; функція 7 (нефільтроване введення без відлуння) Int 21h CMP al, 1 ł ;пробіл? JNZ loopl ; ні! Int 2 Oh ; вихід з програми text DB 25 dup(0ah),0dh ; очищення екрана DB 38 dup (2 Oh) , ' IVAN OLEKS1 ; виведення слова на середину екрана 1 DB 12 dup (Oah) , Odh, ' $ ’ ; Code ENDS END Start
б. ОБ'ЄКТНО-ОРІЄНТОВАНИЙ ПІДХІД У ПРОГРАМУВАННІ 6.1. Технології програмування Технологія програмування - це сукупність засобів та методів розробки програм і порядок їхнього застосування. На ранніх етапах розвитку програмування, коли програми писали як послідовність машинних команд, будь-яка технологія програмування була відсутня. Першими кроками в розробці технології було представлення програми як послідовності операторів. Написанню цієї послідовності передувало складання операторної схеми, що відображає порядок розташування операторів і можливі переходи між ними. Такий підхід дав змогу розробити перші програми для автоматизації складання програм. Із зростанням розмірів програм розпочалось виокремлення фрагментів великої програми та їхнє оформлення у підпрограми. Частину таких підпрограм об’єднували у бібліотеки, з яких підпрограми можна було долучати до робочих програм на етапі компілювання, а потім викликати їх з робочих програм на етапі виконання. Це вважають початком процедурного програмування - велику програму формували як сукупність процедур-підпрограм. Одну з підпрограм вважали головною, і з неї розпочинали виконання програми. Процедурними були перші мови програмування РоНгап і Аіцої. РоНгап -програма налічувала головну програму і деяку кількість підпрограм - процедур і функцій. Програма на мові
394 6.1. Технології програмування А%оІ-60 була єдиним цілим, однак налічувала блочну структуру, що містила головний блок і вкладені блоки підпрограм. Компілятори мови РоНгап забезпечували роздільне транслювання процедур з можливістю їхнього подальшого об’єднання в робочу програму. Перші компілятори для А^оі давали змогу транслювати відразу всю програму. Роздільного транслювання процедур тут не було. Процедурний підхід вимагав структуризування майбутньої програми, тобто її поділу на окремі процедури. На час розробки окремої процедури, щодо інших процедур вимагалося тільки знання про їх призначення і спосіб виклику. Виникла можливість змінювати окремі процедури, не зачіпаючи іншої частини програми. Це скорочувало затрати праці і машинного часу на модернізацію програм. Наступним кроком у поглибленні структуризації програм вважають структурне програмування, за якого програму загалом і її окремі процедури розглядали як послідовності канонічних структур: лінійних ділянок, циклів та розгалужень. З’явилася можливість читати і перевіряти програму як послідовний текст, що підвищило продуктивність праці програмістів під час розробки та налагодження програм. З метою підвищення структурності програми змінились вимоги, що спричинили до більшої незалежності підпрограм. Зазначено, що зв’язок підпрограм із програмами, які їх викликають, необхідно здійснювати тільки через аргументи. Застосування в підпрограмах змінних, що належать іншим процедурам або головній програмі, вважали небажаним. Процедурність і структурність програмування зачепили, передусім, процес опису алгоритму як послідовності кроків, що ведуть від певних початкових даних до шуканого результату. Для вирішення спеціальних задач розпочали , розробляти мови програмування, орієнтовані на конкретний клдс задач: на системи управління базами даних, імітаційне моделювання і т. д. Під час розробки трансляторів більше уваги приділяли виявленню помилок у текстах програм, забезпечуючи цим скорочення витрат часу на налагодження програм. Застосування програм у різних областях людської діяльності спричинило до необхідності підвищення надійності програмного забезпечення загалом. Одним з напрямів вдосконалення мов програмування вважають підвищення рівня типізування даних.
6. ОБ9ЄКТНО-ОРІЄНТОВАНИЙ ПІДХІД У ПРОГРАМУВАННІ 395 Теорія типів даних виходить з того, що кожна змінна, яку використовують у програмі, належить одному і лише одному типу даних. Тип змінної визначає множину її можливих значень і набір операцій, допустимих для виконання над цією змінною. Змінну конкретного типу у певних випадках можна перетворити у змінну іншого типу, проте таке перетворення у програмі необхідно представити явно. Залежно від ступеня виконання перелічених вимог можна говорити про рівень типізування тієї чи іншої мови програмування. Прагнення підвищити рівень типізування мови програмування спричинило до розробки мови Разсаі - мови суворого типізування, хоча в ній передбачено деякі неявні перетворення типів, наприклад, цілого числа в дійсне. Застосування суворого типізування мови під час написання програми дає змогу ще на етапі транслювання вихідного тексту виявити помилки у використанні даних і цим підвищити надійність програми. Разом з тим суворе типізування сковувало свободу програміста, ускладнювало застосування деяких прийомів перетворення даних, необхідних у системному програмуванні. Майже одночасно з мовою Раьсаі розроблено мову Сі, яку значною мірою орієнтовано на системне програмування (вона належить до мов, що слабо типізуються). Будь-яка універсальна мова програмування, незважаючи на відмінності у синтаксисі і ключових словах, які у ній використовують, реалізує одні і ті ж канонічні структури: оператори присвоєння, цикли і розгалуження. В усіх сучасних мовах присутні наперед визначені (базові) типи даних (цілі і дійсні арифметичні типи, символьний і, можливо, рядковий тип), передбачено використання структур даних, зокрема, масивів і записів. Звичні арифметичні операції застосовують щодо арифметичних даних, щодо структурованих даних, зазвичай, передбачено тільки операцію присвоєння і можливість звернення до елементів структури. Разом з тим, під час розробки програми для вирішення конкретної прикладної задачі бажана якнайбільша концептуальна наближеність тексту програми до опису задачі. Наприклад, якщо рішення задачі вимагає виконання операцій над комплексними числами або квадратними матрицями, бажано, щоб у програмі були явно присутні оператори: додавання, віднімання, множення і ділення даних типу комплексного числа;
396 6.1. Технологи програмування додавання, віднімання, множення і обертання даних типу квадратної матриці. Вирішити таку проблему можна декількома шляхами: 1. Побудовою мови програмування, що містить якомога більше типів даних, і вибором для кожного класу задач деякої підмножини цієї мови. Таку мову іноді називають мовою- оболонкою. На роль мови-оболонки претендувала мова PL/1. Проте вона виявилася настільки складною, що так і не вдалося побудувати її формалізованого опису. 2. Побудовою мови, що передбачає розширювання. Така мова містить невелике ядро і допускає розширення, з метою доповнення мови новими типами даних і операторами, що відображають концептуальну суть конкретного класу задач. Таку мову називають мовою-ядром. Подібними властивостями володіли мови Simula і Algol-68. Хоча вони і не набули широкого розповсюдження, проте значною мірою вплинули на розробку інших мов програмування. Подальшим розвитком другого шляху став об’єктно- орієнтований підхід до програмування, який ми розглядатимемо далі [16, 57]. Першу об’єктно-орієнтовану мову програмування Simula 67 розроблено наприкінці 70-х років XX ст. у Норвегії. Вона спочатку призначалась для імітаційного моделювання дискретних подій. Автори цієї мови досить точно передбачили перспективи розвитку програмування: їхня мова значно випередила свій час. Ідеї, закладені у цій мові, слугували джерелом до розвитку цілих напрямів у комп’ютерній науці. Тут вперше застосовано: абстрактні типи даних, які використовують і сьогодні у практиці розробки програмного забезпечення; фрейми, які слугують засобами представлення знань у системах штучного інтелекту; семантичні моделі даних, які покладено в основу розробки систем управління базами даних. У Проте програмісти 70-х років XX ст. виявилися не готовими сприйняти цінності мови Simula 67, і вона не витримала конкуренції з іншими мовами програмування (передусім, з мовою Fortran). Прохолодному відношенню до мови Simula 67 сприяла і та обставина, що її реалізували як інтерпретатор (а не компілятор), що було цілком неприйнятним у 70-ті роки, оскільки інтерпретування взаємозв’язане зі зниженням ефективності
6. ОБ’ЄКТНО-ОРІЄНТОВ АНИЙ ШДХІД У ПРОГРАМУВАННІ 397 (швидкості виконання) програм, а машини тих часів були надто повільними. Достоїнства об’єктної орієнтованості мови Simula 67 визнано наступними поколіннями програмістів: у подальші роки розроблено чимало об’єктно-орієнтованих мов програмування, серед яких SmallTalk, Eiffel, Object Pascal, C-H- та ін. Розробка нових об’єктно-орієнтованих мов програмування продовжується і сьогодні. З 1995 року широкого розповсюдження набула нова об’єктно-орієнтована мова програмування Java, орієнтована, передусім, па. Internet. Після появи мови Simula виникло нове трактування комп’ютерної програми як моделі, що відображає поведінку реального чи уявного фрагмента зовнішнього світу. 6.2. Суть об'єктно-орієнтованого програмування Головні ідеї об’єктно-орієнтованого програмування (ООП) спираються на такі положення: • програма є моделлю деякого реального процесу чи пристрою, частини реального світу; • модель реального світу або його частини можна описати як сукупність об’єктів, які взаємодіють між собою; • об’єкт описується набором параметрів, значення яких визначають стан об’єкта, і набором операцій (дій), які може виконувати цей об’єкт; • взаємодія між об’єктами здійснюється шляхом обміну спеціальними повідомленнями від одного об’єкта до іншого; повідомлення, одержане об’єктом, може вимагати виконання певних дій (наприклад, зміни стану об’єкта); • об’єкти, описані одним і тим самим набором параметрів і здатні виконувати однаковий набір дій, є класом однотипних об’єктів. З погляду мови програмування клас об’єктів можна розглядати як тип даних, а окремий об’єкт - як елемент цього типу. Визначення програмістом власних класів об’єктів для конкретного набору задач дає змогу описувати окремі задачі в термінах самого
398 6.2. Суть об’єктно-орієнтованого програмування класу задач (за відповідного вибору імен типів та імен об’єктів, їхніх параметрів і виконуваних дій). Отже, об’єктно-орієнтований підхід передбачає, що під час розробки програми необхідно визначити класи використовуваних у програмі об’єктів і побудувати їхні описи, потім створити екземпляри необхідних об’єктів і визначити взаємодію між ними. Класи об’єктів зручно будувати так, щоб вони утворювали ієрархічну структуру. Наприклад, клас “Студент”, що описує абстрактного студента, може слугувати основою для побудови класів “Студент 1 курсу”, “Студент 2 курсу” і т. д., які володіють всіма властивостями студента загалом і деякими додатковими властивостями, що характеризують студента конкретного курсу. Під час розробки інтерфейсу з користувачем програми можуть використовувати об’єкти загального класу “Вікно” та об’єкти класів спеціальних вікон, наприклад, вікон інформаційних повідомлень, вікон введення даних і т.п. У таких ієрархічних структурах один клас можна розглядати як базовий для інших, похідних від нього класів. Об’єкт похідного класу володіє всіма властивостями базового класу і деякими власними властивостями. Він може реагувати на ті ж типи повідомлень від інших об’єктів, що й об’єкт базового класу, і на повідомлення, що мають сенс тільки для похідного класу. Зазвичай говорять, що об’єкт похідного класу успадковує всі властивості свого базового класу. Деякі параметри об’єкта можуть бути локалізовані усередині об’єкта і недоступні для прямої дії ззовні об’єкта. Наприклад, під час руху об’єкта-автомобіля об’єкт-водій може впливати тільки на обмежений набір органів управління (рульове колесо, педалі газу, зчеплення і гальма, важіль перемикання передач), проте йому не підвладні .параметри, що характеризують стан двигуна та автомобіля загалом. Окрім того, йому не підвладні органи управління іншого автомобіля, який рухається за ним. Щоб ефективно застосовувати об’єктний підхід для розробки програм, необхідні мови програмування, що підтримують цей підхід, тобто дають змогу будувати опис класів об’єктів, утворювати дані об’єктних типів, виконувати операції над об’єктами. Як ми зазначали, однією з перших таких мов була мова SmallTalk, у якій усі дані слугують об’єктами деяких класів, а загальну систему класів побудовано як ієрархічну структуру на основі похідних від базових класів.
6. ОБ’ЄКТНО-ОРіеНТОВАНИЙ ПІДХІД У ПРОГРАМУВАННІ 399 Досвід програмування засвідчує, що будь-який методичний підхід у технології програмування не повинен застосовуватися сліпо з ігноруванням інших підходів. Це стосується й об’єктно- орієнтованого підходу. Існують типові проблеми, щодо яких перевага цього підходу найочевидніша. До таких проблем належать, зокрема, задачі імітаційного моделювання, програмування діалогів з користувачем. Проте існують задачі, в яких застосування об’єктного підходу ні до чого, окрім зайвих витрат праці, не спричинює. Отож, найбільше поширення набули об’єктно-орієнтовані мови програмування, які дають змогу поєднувати об’єктний підхід з іншими методологіями. У деяких мовах і системах програмування застосування об’єктного підходу обмежується засобами побудови інтерфейсу з користувачем (наприклад, Visual FoxPro ранніх версій). Найпопулярнішими сьогодні об’єктно-орієнтованими мовами є Object Pascal і C++, причому найрозвиненішими засобами для роботи з об’єктами володіє середовище C++. Практично всі об’єктно-орієнтовані мови програмування є мовами, що розвиваються: їхні стандарти регулярно уточнюються і розширюються. Наслідком цього розвитку є неминучі розбіжності у вхідних мовах компіляторів різних систем програмування. Найпоширенішими сьогодні вважають системи програмування фірми Microsoft: C++, Visual C++ і системи програмування Delphi та C++Builder фірми Borland International. 6.3. ООП і Borland Pascal Об’єктно-орієнтовану технологію у мову Pascal фірмою Borland введено у 1989 році. Цією версією був Turbo Pascal 5.5, у яку введено розширення, що підтримувало всі базові аспекти ООП. Це дало змогу численним прихильникам мови Pascal легко та інтенсивно опанувати суть методики та методології ООП. Власне з цього моменту розпочалося інтенсивне проникнення об’єктно- орієнтованої технології в усі сфери прикладного програмування. Керуюча ідея методології ООП полягає у поєднанні даних з процедурами, які ці дані обробляють, в одне ціле - об’єкт. Таке поєднання назвали інкапсулюванням даних і алгоритмів їхньої обробки. Внаслідок цього як дані, так і процедури багато в чому втрачають самостійне значення. Фактично ООП можна розглядати
400 6.3. ООП і Borland Pascal як модульне програмування нового рівня, де замість випадкового, механічного об’єднання процедур здійснено їхній смисловий зв’язок. Головна мета ООП, як і інших підходів до програмування, - підвищення ефективності процесу розробки програм. Ідеї ООП виявилися плідними і їх використовують не тільки в мовах програмування, але й в інших областях комп’ютерних наук (наприклад, в області розробки операційних систем). У традиційних методах програмування зміна даних або методів їхньої обробки часто спричинювала до необхідності корінної переробки структури програми. Усяка суттєва зміна програми - це досить неприємна подія для програміста, адже при цьому збільшується ймовірність помилки, внаслідок чого зростає час, необхідний для налагодження програми. Використання ООП дає змогу знайти вихід з такої ситуації з мінімальними витратами, зводячи необхідну модифікацію програми до її розширення і доповнення. Зазначимо, що переваги ООП максимально проявляються при розробці достатньо складних програм. Спроба використати ООП для програмування дещо простіших програм, що пишуть за готовими формулами, часто виглядає штучним накопиченням непотрібних мовних конструкцій. їх легше і натуральніше розробляти традиційними засобами мови Pascal. Вивчення ідеї ООП - це непроста задача, проте освоєння ООП може суттєво спростити розробку і налагодження складних програм. 6.4. Головні характеристики ООП Методологія ООП як подальший природний розвиток традиційного програмування передбачав більшу ступінь структурованості (ніж у структурному програмуванні), модульності та абстрактності (ніж попередні спроби Абстрагування даних і приховування деталей) програмних засобів. Нова методологія визначається трьома функціональними характеристиками ООП: інкапсулюванням, успадкуванням і поліморфізмом. Дамо пояснення суті кожного з цих понять. Інкапсулювання (encapsulation - об’єднання) - це механізм, який об’єднує в одне ціле дані та алгоритми обробки цих даних. У рамках ООП дані називають полями об’єкта, а алгоритми
6. ОБ’ЄКТНО-ОРІЄНТОВАНИЙ ШДХІД У ПРОГРАМУВАННІ 401 (процедури та функції для обробки цих даних) - об’єктними методами. Поля володіють характеристиками структури Record (запис), яку ми вже вивчали. Об’єднання записів з процедурами і функціями перетворює їхню сукупність у новий тип даних - об’єкт. Об’єкти зберігають структуру, значення і поведінку структури даних, допускаючи набагато завершенішу абстракцію і модульність у програмуванні. Інкапсулювання забороняє або дає змогу одному об’єктові обробляти дані іншого об’єкта з допомогою ключових слів Private і Public. Якщо поле або метод деякого об’єкта позначити як Private, то ніхто до цих даних, крім процедур даного об’єкта, доступитись не зможе, якщо ж помітити - Public, то дані будуть доступними всім. Інкапсулювання дає змогу максимально ізолювати об’єкт від зовнішнього втручання. Воно суттєво підвищує надійність програм, оскільки алгоритми обмінюються з програмою порівняно невеликими обсягами даних, причому кількість і тип цих даних чітко контролюється. Внаслідок цього, заміна чи модифікація алгоритмів та даних, інкапсульованих в об’єкт, зазвичай, не спричинює негативних наслідків для програми загалом (з метою підвищення захисту програм в ООП практично не використовують глобальних змінних). У традиційному підході до програмування з використанням глобальних змінних програміст не міг оминути помилок, що стосувались використання процедур, не призначених для обробки даних, зв’язаних з цими змінними. Припустимо, наприклад, що існує “не об’єктно-орієнтована” програма, яка призначена для нарахування заробітної плати співробітникам деякої організації, а в цій програмі є два масиви. Один масив зберігає величину заробітної плати, а другий - телефонні номери співробітників. Уявіть собі, що станеться, якщо програміст випадково переплутає ці масиви? Очевидно, для бухгалтерії почнуться важкі часи. “Жорстке” зв’язування даних і процедур їхньої обробки в одному об’єкті дає змогу уникнути таких неприємностей. Інкапсулювання і слугує засобом організації доступу до даних для їхньої обробки тільки через відповідні методи. 2. Успадкування (inherited): опис об’єкта з подальшим використанням його складових частин для побудови ієрархії породжених об’єктів з успадкуванням кожного з породжених
402 6.4. Головні характеристики ООП об’єктів, доступу до процедур і даних предка. Пояснимо детальніше ідеї успадкування. Метою науки є вивчення та опис взаємодій між предметами реального світу. Щоб зрозуміти ці взаємодії, вчені класифікують предмети: будують функціональні схеми, у яких кожна частина складного предмета одержує свою назву, місце стосовно інших частин, а також спосіб взаємодії кожної з частин між собою. Результатом такої роботи є побудова ієрархічної схеми, подібної до генеалогічного дерева, відомого нам з історії. Коли ентомологу вдалось упіймати невідому раніше комаху, то, досліджуючи її, він, передусім, визначить місце цієї комахи у гігантській схемі, де уже зібрано наукові назви усіх інших комах. Аналогічні схеми складено для всіх рослин, хімічних елементів, елементарних частинок, технічних пристроїв і т. д. Всі вони виглядають як генеалогічні дерева; з єдиною загальною категорією на вершині та всезростаючою кількістю категорій, які лежать нижче цієї загальної категорії, що розгортаються віялом, відповідно до наближення до нижнього краю. Кожна категорія містить значну кількість підкатегорій, які, в свою чергу, розгалужуються на ще більше число підкатегорій. На рис. 6.1 наведено невелику частину схеми класифікування радіокомпонент. Такий процес класифікування називають таксономією. Це хороша метафора для розуміння механізму успадкування в об’ектно-орієнтованому програмуванні. Рис. 6.1. Таксономічна схема радіокомпонент
6. ОБ’ЄКТНО-ОРІЄНТОВАНИЙ ШДХІД У ПРОГРАМУВАННІ 403 За спроби класифікування деякої комахи чи технічного об’єкта учений задає собі такі запитання: чим досліджуваний екземпляр є подібний на інші екземпляри із загального класу, а чим він відрізняється від інших? Кожен конкретний об’єкт має безліч властивостей і характеристик, що визначають набір об’єктів. Учений починає з вершини конкретного генеалогічного дерева, досліджує дочірні області, ставлячи собі ці запитання. Чим вищий рівень узагальнення, тим подібні питання є простішими. Наприклад, дана радіокомпонента є дискретною чи інтегральною? Кожен подальший рівень є специфічнішим, ніж попередній, і не таким узагальненим. Врешті-решт, учений визначає габарити, потужність чи вольт-амперні характеристики компоненти. Об’єктно-орієнтоване програмування значною мірою слугує процесом побудови генеалогічного дерева для структур даних. Однією з важливих особливостей, яку об’єктно-орієнтоване програмування додає традиційним мовам типу Разсаі, є механізм, за допомогою якого типи даних можуть успадковувати характеристики простіших, узагальненіших типів. Цим механізмом є успадкування. Поняття структури завжди асоціюється зі складним об’єктом, що володіє властивістю цілісності, і разом з тим складеним, за певною системою правил, з простих компонент (частин, елементів). Програмування можна інтерпретувати як мистецтво розкладання і класифікації всієї задачі, що підлягає вирішенню, на частини. Це розкладання називають декомпозицією. Щодо цього структури- зацію в програмуванні можна трактувати як правила виконання такої декомпозиції. Декомпозицію можна, звичайно, здійснити і без правил, однак у цьому випадку (як і в будь-якій грі без правил) важко зрозуміти, а в загальному випадку - і неможливо, як з частин утворюється структура. Історично структуризація в програмуванні розпочиналася з введення у мови програмування управляючих структур - операторів умовного переходу, вибору, циклів з різними правилами повторення і виходу і т. п. Мета такої структуризації полягає у підвищенні її читабельності, тобто у полегшенні процесу розуміння програм, що розробляються. В об’єктно-орієнтованій парадигмі присутня ієрархічна модель в організації класів/об’єктів. Природно, що не всі задачі можна описати цим видом моделей. Проте, зауважимо, що більг
404 6.4. Головні характеристики ООП шість задач можна розв’язувати з допомогою ієрархій. Людині властиве ієрархічне мислення - це найпоширеніший спосіб роботи зі “складністю”. 3. Поліморфізм - це властивість об’єктів-родичів (тобто об’єктів, котрі мають одного спільного предка) вирішувати схожі за змістом проблеми різними способами, тобто властивість, яка дає змогу однотипні речі для різних об’єктів робити по-різному, проте називати їх однаково. У рамках ООП властивості об’єкта визначаються набором методів, які до нього належать. Змінюючи алгоритм того чи іншого методу в нащадках об’єкта, програміст може надавати цим нащадкам відсутніх у предка специфічних властивостей. Щоб змінити метод, необхідно перекрити його в нащадку, тобто оголосити в нащадку однойменний метод і реалізувати у ньому потрібні дії. Внаслідок цього в об’єкті- предкові і в об’єкті-нащадкові діятимуть два однойменних методи з різною алгоритмічною основою, які, відповідно, надаватимуть об’єктам різні властивості. Це і називають поліморфізмом об’єктів. Прикладом поліморфізму у мові Pascal є поліморфна операція “додавання” (“+”): ця операція може додавати за різними алгоритмами як дійсні, так і цілі числа, а також додавати (об’єднувати) два текстові масиви. У Borland Pascal поліморфізму досягають не тільки описаним вище механізмом успадкування і перекриття методів предка, але й їхньою віртуалізацією,^ котра дає змогу методам предків звертатися до методів нащадка (з цією метою необхідно використати ключове слово Virtual). Об’єктно-орієнтоване розширення мови Pascal підтримує три зазначені вище визначаючі характеристики ООП, не порушуючи щодо цього * надійності стандартних конструкцій мови. Використання цієї технології змушує змінити традиційні звички і способи мислення у програмуванні, оскільки полегшує розв’язання багатьох проблем, важких для традиційного прбграмування. 6.5. Проектування (створення) об'єктів у ВР Вивчення будь-якої нової структури у програмуванні мовою Pascal необхідно розпочинати з визначення способу описання цієї структуру і правил використання її в операторах програми. Уточнимо поняття об’єкт, Об’єкт - це новий тип даних, який
6. ОБ’ЄКТНО-ОРІЄНТОВАНИЙ ШДХІД У ПРОГРАМУВАННІ 405 об’єднує в собі дані (поля) та алгоритми, які ці дані обробляють, об’єднані у формі процедур і функцій, тобто методи. У ВР для створення об’єктів використовують три зарезервованих слова: Object, Constructor і Destructor і три стандартних директиви: Private, Public, Virtual. Опис нової структури даних Object поміщаємо у розділі опису нових типів. Загальна форма цього опису є такою: Type FirstObject = Object {поля об'єкта} {методи об'єкта} End ; Якщо об’єкт не є первинним, а породжується від деякого предка, ім’я цього предка подаємо у круглих дужках відразу за словом Object Type NewObject = Object ( FirstObject ) {поля об'єкта} {методи об'єкта} End ; Ми описали новий об’єкт на ім’я NewObject, який є нащадком об’єкта FirstObject. У ВР є зарезервоване слово Inherited, яке використовують для визначення об’єкта-предка. Зазвичай, Inherited не можна використовувати в тих об’єктах, які не мають предка. Успадкування - це властивість об’єктів породжувати своїх нащадків, тобто ця властивість передбачає збільшення кількості об’єктів без перепрограмування процедур, зроблених для об’єкта-предка. Об’ єкт-нащадок автоматично успадковує від “предка” всі поля і методи, до яких може долучати свої власні нові поля і методи або замінити (“перекрити”) їх своїми методами. З методів нащадка можна викликати методи предка. Створення нащадка не потребує вихідного тексту об’єкта-предка. Об’єкг-предок може входити до складу попередньо відтрансльо- ваного модуля. Директива Private в описі об’єкта відкриває секцію опису прихованих полів і методів. Перелічені у цій секції елементи об’єкта “невидимі” програмістові, так ніби цей об’єкт він отримав в
406 6.5. Проектування (створення) об’єктів у ВР рамках бібліотечного /pw-модуля. Приховуються, зазвичай, ті поля та методи, до яких програміст не повинен мати безпосереднього доступу. Директива Public скасовує дію директиви Private. Усі елементи об’єкта, наступні за Public, є доступними будь-якій програмній одиниці. Директиви Private і Public в рамках одного об’єкта можуть чергуватися довільно. Для опису методів у рамках ООП використовують традиційні щодо мови Pascal процедури та функції, а також особливий вид - конструктори і деструктори. Конструктори призначені для створення конкретного екземпляра об’єкта, оскільки об’єкт - це тип даних, тобто “шаблон”, за яким можна створювати скільки завгодно робочих екземплярів даних об’єктного типу. Зарезервоване слово Constructor, яке використовують у заголовку конструктора замість Procedure, призначає компіляторові створити особливий код прологу, за яким настроюють таблицю віртуальних методів (ТВМ). Якщо в об’єкті немає віртуальних методів, у ньому може і не бути жодного конструктора. І навпаки: якщо хоча б один метод описано як віртуальний (з наступним словом Virtual), то об’єкт повинен налічувати хоча б один конструктор і звертання до конструктора повинно випереджати будь-яке звертання до будь- якого віртуального методу. Типова дія, реалізована конструктором, базується на тому, щоб наповнити об’єктні поля конкретними значеннями. Зауважимо, що різні екземпляри одного і того ж об’єкта відрізняються один від одного лише вмістом об’єктних полів, проте кожен з них використовує однакові об’єктні методи. На відміну від конструктора, який настроює ТВМ, деструктор, який описують зарезервованим словом Destructor, не зв’язаний з будь-якими специфічними діями: для компілятора слова Destructor та Procedure - синоніми. Введення в ООП деструкторів має, здебільшого, стилістичний характер. Процедуру, котра руйнує екземпляр об’єкта, прийнято називати деструктором. Насправді в ООП з деструкторами поєднують процедури, які не тільки припиняють роботу з певним об’єктом, але й звільняють виокремлену йому динамічну пам’ять.
6. ОБ'ЄКТНО-ОРІЄНТОВАНИЙ ПІДХІД У ПРОГРАМУВАННІ 407 У термінах мови Pascal об’єкт багато в чому нагадує запис, який слугує оболонкою для об’єднання декількох логічно взаємозв’язаних різнотипних елементів під одним іменем. Наприклад, нехай необхідно написати програму виведення на друк звіту про зарплату працівників деякої фірми, яку доведеться сплатити кожному службовцю за один робочий день. Спочатку створимо такий запис: Туре ТЕшрІоуее = Record Name, Title : String [25] ; Rate : Real; End; Примітка: Доцільно власні типи завжди розпочинати з літери т. Це є загальноприйнятою угодою. Тут ТЕїпрІоуее слугує новим типом запису, тобто шаблоном, який використовуватиметься компілятором для створення змінних типу Record. Кожна змінна типу TEmployee, яку ми опишемо у розділі Var, слугуватиме екземпляром цього типу. Термін “екземпляр” постійно застосовують під час використання методів ООП, отож, доцільно навчитись мислити у термінах типів та екземплярів цих типів. З типом ТЕшрІоуее можна оперувати двояко. Можна розглядати поля Name, Title і Rate окремо або загалом, тобто для опису даних щодо конкретного співробітника. Припустимо, що на фірмі працює декілька типів співробітників: перші мають погодинну оплату, другі - оклад, треті - тарифну ставку і т.д. Наша програма покликана врахувати усі ці типи. Ми можемо створити ще один запис для кожного типу робітника. Наприклад, для отримання даних щодо зарплати робітника з погодинною оплатою праці необхідно знати, скільки годин він відпрацював. Можна побудувати запис THourly вигляду: THourly = Record Name, Title : String [25] ; Rate : Real; Time : Integer; End;
408 6.5. Проектування (створення) об’єктів у ВР Оскільки перші три поля типів ТЕшрІоуее і THourly збігаються, ми можемо сформувати комбінований тип шляхом створення поля типу TEmployee усередині типа THourly: THourly = Record Worker : TEmployee; Time : Integer; End; Таку конструкцію вважають синтаксично коректною, програмісти використовують її постійно. Запис для працівника-погодинника THourly повинен налічувати усі поля, які є в записі Temployee. Тип THourly є типом- нащадком для типу ТЕшрІоуее. THourly успадковує все, що належить Temployee. Окрім того, він має дещо нове, що робить THourly унікальним. Процес, за допомогою якого один тип успадковує характеристики іншого типу, називають успадкуванням. Отже, ми створили батьківський тип і тип породжений, або дочірній. Можливість робити подібне надає об’єктно-орієнтоване розширення мови ВР. Це розширення дає змогу створити нову категорію структури даних, значно потужнішу за Record. Типи даних у цій новій категорії визначаються за допомогою нового зарезервованого слова Object. У нашому прикладі звіту щодо зарплати, два взаємозв’язані типи об’єктів можна описати так: Туре ТЕшрІоуее = Object Name, Title : String [25]; Rate : Real; End; THourly = Object (ТЕшрІоуее) Time : Integer; End; Тут ТЕшрІоуее є батьківським типом, a THourly - дочірнім типом. Застосування дужок означає успадкування. Процес побудови ієрархії типів можна продовжувати далі. Описавши дочірній тип THourly, можна створити тип дочірній до типу THourly і т. д. Значна частина процесу конструювання об’єктно- орієнтованих прикладних програм передбачає побудову такої ієрархії об’єктів. Усі можливі типи, що успадковують тип TEmployee, називаються дочірніми типами типу ТЕшрІоуее, проте THourly є
6. ОБ’ЄКТНО-ОРІЄНТОВ АНИЙ ПІДХІД У ПРОГРАМУВАННІ 409 безпосереднім дочірнім типом типу TEmployee. І навпаки, TEmployee є безпосереднім предком типу THourly. Структура даних: об’єкт, може налічувати будь-яку кількість безпосередніх дочірніх типів, однак матиме тільки одного безпосереднього предка. Наведений приклад засвідчує, що об’єкти дуже подібні до записів. Нове зарезервоване слово Object є найочевиднішою розбіжністю, проте існує значна кількість інших специфічних розбіжностей. Наприклад, поля Name, Title і Rate, які присутні у типі тешріоуее, не зазначені явно у типі THourly, однак у будь- якому випадку тип THourly містить їх завдяки властивості успадкування. Тобто величину Name типу THourly можна використовувати цілком так само, як величину Name типу TEmployee. Екземпляри об’єктних типів описують за тими самими правилами, як в мові Pascal описують будь-яку змінну або вказівник, що посилається на розташовану в динамічній пам’яті змінну: Type PHourly = ATHourly; Var StatHourly : THourly; DynaHourly : PHourly; {перед застосуванням пам’ять необхідно виокремлювати за допомогою New}. До поля об’єкта можна звертатися так само, як до поля звичного запису, або за допомогою оператора With, або шляхом уточнення імені за допомогою крапки. Наприклад. AnHourly.Rate := 9.45; With AnHourly do Begin Name := 'Петро Біда'; Title := 'Word processor' End; Зауважимо, що успадковані поля є такими ж доступними, наче їх оголошено усередині типу об’єкта. Наприклад, навіть якщо Name, Title і Rate не є частиною опису типу THourly (вони успадковані від типу TEmployee), то ми можемо використовувати так, наче їх описано в THourly: AnHourly.Name := 'Петро Біда';
410 6.6. Програма, що демонструє принципи ООП б.б. Програма, що демонструє принципи ООП Продемонструємо принципи побудови простої ООП програми, яка на графічному екрані виводить серію різнокольорових фігур, що рухаються вздовж діагоналі екрана. Program XIO_Demo_Ob j; Uses Crt, Graph; Type Figura = Object { опис об'єктного типу даних) Procedure Set_Fig; { розділ методів } Procedure Draw; Virtual; Procedure Hide; Procedure Resize (k : Real); Virtual; Procedure Move (dx, dy : Integer); Private { розділ "прихованих" полів } x0, y0, color : Integer; End; { завершення опису Figura) Kolo = Object (Figura) { опис нащадка типу Figura } Constructor Init; Procedure Draw; Virtual; Procedure Resize (k : Real); Virtual; Private R : Integer; End; { завершення опису об'єкта Kolo) Kvadrat = Object (Figura) {опис ще одного нащадка типу Figura } Constructor Init; Procedure Draw; Virtual; Procedure Resize (k : Real); Virtual; > Private a : Integer; End; { завершення опису об'єкта Kvadrat) { Завершення розділу опису об’єктних типів } { Описуємо два масиви із 16-ма елементами типу Kvadrat і Kolo } Var А : Array [1..16] of Kvadrat; В : Array [1..16] of Kolo; i, dx, dy : Integer; { Описуємо процедури - методи наших об’єктів } " Procedure Initialize; Var Drv, Drm : Integer; Begin Drv := Detect; InitGraph (Drv, Drm, ’C:\BP\BGI1); End; Procedure F і gura.S e t_Fi g;
6. OB’CKTHO-OPI6HTOBAHHH niflXIfl y nPOrPAMYBAHHI 411 Begin Color := i; xO := i * 10; y0:=i*5+50; End; Procedure Figura.Draw; Begin PutPixel (xO, yO, Color); End; Procedure Figura.Hide; Var c : Integer; Begin C := Color; Color := 0; Draw; Color := c; End; Procedure Figura.Resize (k : Real); Begin End; Procedure Figura.Move(dx, dy : Integer); Begin xO := xO + dx; yO := yO + dy; End; Constructor Kolo.Init; Begin Set_Fig; r := 100 - 5 * i; End; Procedure Kolo.Draw; Begin SetColor (color); Circle (xO, yO, r) End; Procedure Kolo.Resize(k : Real); Begin r := Trunc (r * k) End; Cons truetor Kvadrat.Init; Begin
412 6.6. Програма, що демонструє принципи ООП Set__flg; а := 5 * і End; Procedure Kvadrat.Draw; Begin SetColor (color); Rectangle (xO, yO, xO + a, yO + a) End; Procedure Kvadrat.Resize (k : Real); Begin a := Trunc (a * k) End; { Початок головної програми } BEGIN For і := 1 to 16 do Begin a[i].init; b[i].init; End; Initialize; For і := 1 to 16 do Begin a[i].draw; b[i].draw; End; dx := 2; dy := 2; Repeat For і := 1 to 16 do Begin a[i].hide; a[i-] .move(dx, dy) ; a[i].draw; b[i].hide; b [i] .move (dx, dy) ; b[і].draw End; Delay{20); Until KeyPressed END.
7. МЕТОДИ Й АЛГОРИТМИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 7.1. Розробка головної програми Можна виокремити три головні шляхи отримання експериментальних результатів у формі числових масивів: 1) візуальне зчитування показів вимірювальних приладів або “ручна” обробка графіків від самописців; 2) дискретизація (табулювання) аналітичних функцій, які наближено чи точно описують поведінку певного фізичного процесу або системи; 3) електронне аналогово-цифрове перетворення інформації, яка надходить від вимірювальних приладів і автоматичний запис дискретних відліків у пам’ять ПК. Перший спосіб недосконалий і найважчий, оскільки вимагає ручного введення в ПК громіздких масивів чисел. Другий спосіб передбачає програмну дискретизацію аналітичної функції шляхом її табулювання із записом результатів у масиви. Третій спосіб можливий, якщо є спеціальні пристрої для автоматизації експерименту. Для дослідження алгоритмів обробки експериментальних результатів необхідно спочатку розробити головну програму (ГТІ). Вона призначена для організації процесу введення числових даних у пам’ять ПК з метою подальшої їхньої обробки і відображення результатів. Передбачено введення даних або з клавіатури, або шляхом програмного обчислення дискретних значень тестової
414 7.1. Розробка головної програми функції (табулювання), або з текстового файла, який попередньо формується завдяки NUMERI NUMERI - це простий в освоєнні компактний (обсяг його 430Кб) детально документований пакет, який вільно поширювався як додаток до книжки з його описом [111]. Пакет налічує файли NUMERI.exe, NUMERI, dis, NUMERI.dsc, NUMERI.hlp, NUMERI.ovІ і декілька необов’язкових файлів *.ху з текстовими наборами значень функцій, які задані у формі таблиці. Рядок кожного із файлів *.ху має довжину 48 символів. Він містить символьне зображення двох чисел у форматі із плаваючою комою по 23 символи кожне з двома пробілами між ними. Пакет дає змогу користувачеві вводити різні алгебричні функції у символьній формі, обробляти ці функції чисельними методами, записувати результати обробки у текстові масиви, відображати результати на графічний екран ПК. Отож, він слугує зручним допоміжним інструментом для вивчення методів і алгоритмів комп’ютерної обробки результатів експерименту. 7.1.1. Методичні вказівки Блок-схему ГП зображено на рис. 7.1. В описовій частині програми введемо новий тип даних: одновимірний масив чисел дійсного типу розміру [0 . . 640] . Наприклад: % Type Vector = Array[0.. 640] of Real;. Опишемо чотири глобальні змінні новоствореного типу: Хе, Ye - вхідні масиви даних; Xg, Yg - вихідні масиви результатів обробки вхідних даних чисельним методом. У блоці 1 відбувається введення числа експериментальних значень Ne і числа вихідних значень Ngr (кількість точок графіка вихідної функції). Оскільки програма використовує текстовий файл, його описують так: Fv ; Text;. Вибір варіанта заповнення масивів-'Хе і Ye здійснюється шляхом введення ознаки kl, яка набуває одного із трьох значень: 1 - введення масивів Хе і Ye з клавіатури; 2 - табулювання заданої функції і запис результатів у масиви Хе і Ye ; 3 - зчитування і запис в Хе і Ye вмісту текстового файла, який попередньо сформовано пакетом NUMERI.
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 415 Передачу керування відповідному варіанту введення найкраще здійснювати оператором ВР\ Case kl of . Набір експериментальних значень або тестову функцію задає викладач. Для варіанта KL = 1 операторі введення (тіло циклу) зручно оформити так: Write ( 'Хе[\ Хе[і] ) ; Read ( Хе [ і ] ) ; Write ( 'Ye[' , і Ye[і] ) ; Readln ( Ye[і]); Для створення варіанта KL = 2 використаємо оператори табулювання функції. Під час роботи з текстовим файлом (варіант: kl = 3) формуємо його так: Запускаємо NUMERI. Одержимо таке цифрове меню: 0 Сервісні програми 1 Статистика 2 Розподіл амплітуд 3 Інтерполювання 1 апроксимування даних 4 Згладжування, диференціювання, інтегрування 5 Дискретне перетворення Фур'є 6 Цифрові фільтри 7 Кореляція Обираємо варіант |#|. Одержимо таке меню: 1 Дані 2 Знаходження коренів 3 Розв'язування систем рівнянь 4 Графічне накладання файлів Натиснувши [/], одержимо: 1 Створення даних 2 Обробка даних 3 Зашумлення даних 4 Порівняння файлів Обираючи 0, одержимо : 1 Дані із інтерпретатора формул 2 Дані із файла на диску/дискеті 3 Введення даних з клавіатури 4 Генерування стандартних сигналів * 5 Виведення набору даних Обираючи З, одержимо можливість ввести задану функцію, межі проміжку її дослідження і кількість точок табулювання.
416 7.1. Розробка головної програми Екран набуде вигляду: у(х) задаємо зіп(х) Другий рядок = від х = 0 ( задаємо 0 ) до х = 0 ( задаємо 6.28 ) Кількість опорних точок = 0 ( задаємо, наприклад, 15) Крок = 0 ( вибереться автоматично ) Е1 -Допомога ПО -Далі Езс - Вихід Натиснувши клавішу \F1C\, одержуємо меню: 1 Графік 2 Таблиця 3 Записати 4 Змінити заголовок 5 Розширене меню графіки Обираючи варіант [з], записуємо отримані дані на диск. Тут необхідно задати ім’я нашого текстового файла та увесь шлях до підкаталогу, куди його необхідно записати (виникне підказка): Записати файл: (тут вводимо ім’я файла без розширення) Поточний каталог: (вводимо, наприклад: D:\F-21\ABC). Натискаючи клавішу \FlCj, запишемо файл. Вихід з NUMERI здійснюємо послідовним натисканням клавіші |Esd, двічі підтверд- "* жуючи своє бажання закінчити роботу з програмою (відповідаючи на запит програми). Обробку текстового файла виконаємо так: ( див. блоки 20-28 рис. 7.1). Відкривши файл процедурами ВР: Assign (Fv, < ім'я дискового файла >); і Reset: (Fv); , у циклі здійснюємо послідовне зчитування рядків файла та їхній запис у текстову змінну LF (її довжина 48 символів). Виокремлюємо з LF спочатку перше, потім - друге число у символьній формі. Переводимо ці числа з символьного представлення у машинне ^ записуємо їх у відповідні елементи масивів Хе і Ye. Останні дві операції виконує функція ВР типу String: Copy (<ім'я вихідної текстової змінної>, <початок тексту>, <кількість його символів>);
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 417 і процедурою з трьома параметрами: Val (<±м'я вхідної текстової змінної>,<±м'я вихідної змінної дійсного типу>, <змінна. типу Integer, куди буде записано код результату виконання*процедури>) ; Після заповнення масивів Хе і Ye можна виконувати їхню обробку. У цьому розділі ми досліджуватимемо спектральний метод, методи інтерполювання і методи апроксимування результатів. Здебільшого, для оптимізації процесу обчислень в алгоритмах, які реалізують ці методи, виокремлено підготовчі модулі одноразового виконання та модулі, які в процесі виконання йашої задачі виконуються багаторазово. Від’єднання одноразових модулів після виконання ними необхідних обчислень, відбувається шляхом логічного порівняння значення деякої змінної (ключа) з нулем. Якщо це значення дорівнює нулеві - модуль виконується й унаслідок цього відбувається зміна значення ключа на одиницю. У ГТІ ключем слугує змінна kl. Її занулення відбувається у 29 блоці (рис. 7.1). У цьому ж блоці відбувається заповнення числовими значеннями змінних al і bl (початку і кінця проміжку зміни аргументу) для випадку введення даних з клавіатури чи текстового файлам Усі алгоритми обробки експериментальних результатів, які тут вивчатимемо, необхідно програмувати як Ра$са/-процедури. Виклики цих процедур почергово поміщатимуться на місці 30-го блока ГП. Очевидно, що тексти самих процедур, згідно зі структурою Ра5са/-програми, перебуватимуть на початку ГП, за описом типів змінних. Кожен алгоритм обробки доцільно оформляти як окремий дисковий файл і під’єднувати його до ГП або як Pascal-модуля оператором uses <ім'я модуля>;, або як текстовий файл директивою компілятора {$і <ім'я файла>.pas}. Результатом виконання модулів обробки слугуватимуть масиви вихідних даних Xg і Yg. У блоці 31 ГП викликають модулі побудови графіків. Завдання для самостійної роботи 1. Написати PascaZ-програму згідно з блок-схемою рис. 7.1. 2. Освоїти роботу в середовищі пакета NUMERI, створивши текстові файли заданих викладачем тестових функцій. 3. Продемонструвати працездатність кожної з логічних віток ГП шляхом виведення на графік наборів даних, які введені кожним із перелічених способів. 14 7-451
418 7.1. Розробка головної програми Рис. 7.1. Алгоритм побудови головної програми для дослідження методів комп’ютерної обробки експериментальних результатів
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 419 7.2.2. Головна програма XIO__GOL_Prog Program XIO_GOL_Prog; {$М 64000,200000,264000} Uses Crt, Graph; Type Extended = Real; Vector = Array [0..600] of Extended; Vec = Array [0..40] of Extended; Matrix = Array [1..20, 1..20] of Extended; Var Xe, Ye, Xg, Yg : Vector; KP : Vec; MaxX,MaxY,MinX,MinY, Kx, Ky, Zx, Zy, Gx, Gy : Extended; MaxYg,MinYg, xx, yy : Extended; al, bl, h, TP, w, ay, bx, Krx, Kry : Extended; Lf : String [48] ; k2 : String [23] ; Fv, Fx : Text; Ne,Ngr,Ng, KL, i,j, KrokX,KrokY, Drv,Drm, L,M : Integer; Txt : String; Function f (x : Extended) : Extended; Begin TP := bl - al ; If x < TP / 2 then f := 1{! »Тільки для ряду Фур'є ! !} else If (x >= TP / 2) and (x < 3 * TP / 4) then f := 4 * (TP - 2 * x) / TP else f := 8 *(x - TP) / TP End; {$1 Fur je. pas} {Під'єднання процедури Фур'є} BEGIN Writeln ( !Вв. к-сть експ. зн. Ne і к-сть точок графіка Ngr1); Readln (Ne, Ngr); Writeln (’Введіть ознаку KL1); Writeln (f1- клавіатура’); Writeln (’2- табуляція’); Writeln (’3- текст, файл’); Readln (KL); Case KL of 1: Begin Writeln (’Введіть експер. результати’); For і := 0 to Ne - 1 do Begin Write (’Xe[’, i, ’]=’); Read (Xe[±]); Write (’Ye[’, i, ’]=’); Read (Ye[i]) End End; 2: Begin Writeln (’Введіть проміжок al bl’);
420 7.1. Розробка головної програми Readln (al, Ь1)/ Н := (bl - al) / (Ne - 1) ; Хе[0] := аі; For і := 0 to Ne - 1 do Begin Ye[і] := f (Xe[i]); Xe[i + 1] := Xe[i] + h End End; 3: Begin Assign (Fv, 'XIO.xy'); Reset (Fv); For i:=0 to Ne - 1 do Begin Readln (Fv, Lf); k2 := Copy (Lf, 0, 23); Val (k2, Xe[i], j); k2 :=Copy (Lf, 26, 23); Val (k2, Ye[i], j) End End End; KL := 0; al := Xe[0] ; bl := Xe [Ne - 1] ; Furje (Xe, Ye, Ne, Yg) ; { Виклик процедури Фур'є } Drv := Detect; InitGraph (Drv, Drm, ’C:\Bp\Bgi'); SetBkColor (Whi te); L := 60; MinX := Xe[0]; MaxX := Xe[Ne - 1] ; MinYG := Yg[0]; MaxYg := Yg[0J; For i:=0 to Ngr - 1 do Begin If MaxYg < Yg[i] then MaxYg := Yg[i]; If MinYg > Yg[i] then MinYg := Yg[i]; End; MinY :=* Ye[0]; Maxy := Ye[0]; For і := 0 to Ne - 1 do Begin If MaxY < Ye[i] then MaxY := Ye[i]; If MinY > Ye[i] then MinY := Ye[i] End; / If MaxY < MaxYg then/MaxY := MaxYg; If MinY > MinYg then MinY := MinYg; Kx := (GetMaxX - 2 * L) / (MaxX - MinX) ; Ky := (GetMaxY - 2 * L) / (MinY-MaxY) ; Zx := (GetMaxX * MinX - L*(MinX + MaxX))/(MinX - MaxX); Zy := (GetMaxY * MaxY - L*(MinY + MaxY))/(MaxY - MinY); If MinX * MaxX <= 0 then Gx := 0; If ( MinX * MaxX > 0 ) then Gx := MinX;
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 421 If ( MinX * МахХ > 0 ) And ( MinX<0 ) then Gx := MaxX; If ( MinY * MaxY <= 0 ) then Gy := 0/ If ( MinY * MaxY > 0 ) And ( MinY>0 ) then Gy := MinY; If ( MinY * MaxY > 0 ) And (. MinY<0 ) then Gy := MaxY; ay := Kx * Gx + Zx; bx := Ky * Gy + Zy; SetColor (Red); SetLineStyle(0, 2, 3) ; Line (L, Round (bx) , Round (GetMaxX - L) , Round (bx) ) ; Line {Round (ay), L, Round (ay), Round {GetMaxY - L) ) ; SetLineStyle (3, 0, 1); SetColor (Green); KrokX := ( GetMaxX - 2 * L) Div 10; KrokY := ( GetMaxY - 2 * L) Div 10; For i:=l to 9 do Begin Line (L, L + і * KrokY, GetMaxX - L, L + і * KrokY); line (L + і * KrokX, L, L + і * KrokX, GetMaxY - L ) ; Krx := (MaxX - MinX) / 10.0; Kry := (MaxY - MinY) / 10.0; End; XX := MinX; уу := MaxY; SetTextStyle (2, 0, 5) ; For i:=0 to 10 do Begin Str (xx:7:2, Txt); SetTextJustify (0, CenterText); OutTextXY (L-8+i*KrokX, GetMaxY - L Div 2-5, Txt); SetTextJustify (CenterText, CenterText); Str (yy:7:3, Txt); OutTextXY (L - 30, L + і * KrokY, Txt); xx := xx + KrX; yy := yy - KrY; End; SetColor{Blue); For і := 0 to Ne - 1 do For j 1 to 2 do Circle (Round (Kx*Xe [i] +Zx) , Round (Ky*Ye [i]+Zy) , j); SetColor ( Red ); SetLineStyle(0,0,3); MoveTo(Round (Kx*Xe[0] + Zx) ,Round(Ky*Yg[0] + Zy) ) ; For і := 0 to Ngr - 1 do LineTo{Round (Kx*Xe[i] + Zx) ,Round(Ky*Yg[i] + Zy) ) ; SetColor (Green); SetLineStyle (0, 0, 1); RectAngle (L, L, GetMaxX - L, GetMaxY - L) ; Repeat Until KeyPressed; END.
422 7.2. Спектральний аналіз періодичних сигналів 7.2. Спектральний аналіз періодичних сигналів У багатьох розділах фізики - акустиці, гідродинаміці, електротехніці, оптиці - досліджують коливні періодичні процеси, що описані функцією у=/(0, яка визначена для всіх дійсних значень аргументу ґ і має властивість /(ї+ТР)=/(0, де ТР- період коливань. Перетворення Фур’є здійснює перехід від /(і) до функції іншого аргументу ср(ч), де у=1/ТР . Якщо аргументом є час, то V - лінійна частота. В оптиці за допомогою цього перетворення переходять від функції, де незалежною змінною є довжина хвилі Л, до функції від оберненої до Я величини к, яку називають хвильовим числом [51]. Перехід / ->(р називають прямим перетворенням Фур’є, а <р->/ - зворотним перетворенням. Якщо функцію /$) задано у формі таблиці, наприклад, отримано з експерименту, то тут використовують дискретне перетворення Фур’є. Якщо кількість експериментальних результатів становить степінь числа 2, то застосовують алгоритм швидкого перетворення Фур’є (ШПФ) - сучасний потужний метод цифрової обробки сигналів [64]. Ряд Фур’є дає змогу представити періодичний процес /(0 сумою гармонічних^ коливань, частоти яких є кратні основній частоті V. ЯО^+^(атсов(2кут0+ьтт(2мтф=^+^(атсо5(^)+Ьт!т(тм/ф, ^ /77=7 ^ т=1 (7.2.1) де м?=2лу - кругова частота. З погляду фізики ряд (7.2.1) можна інтерпретувати, як заміну складного руху фізичної системи сумою простих гармонічних рухів, які відбуваються одночасно. У фізиці коливань і хвиль для означення простих рухів, поряд із терміном гармоніка, використовують термін мода [51]. Для визначення коефіцієнтів ряду помножимо вираз (7.2.1) на соб^Ьі^ (к - ціле число) і проінтегруємо його на відрізку [0, ТР]. Враховуючи ортогональність системи функцій { соб(Ьуі), $т(кжґ) }, одержимо [55]:
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 423 ТР І ЛО«* (7.2.2) °к=~; І /фсо5(Ы0Ж (7.2.3) 0 7Р 7Р о Помножимо (7.2.1) на і проінтегруємо добуток на відрізку [0, ТР]. Одержимо: ТР ьк=— І /тп(Ы№, деі= 1,2,3... (7.2.4) 0 Ряд (7.2.1) можна записати по іншому: №=,Ц-+'Е'ск<х*(Ьм-щ:), (7.2.5) 2 к=1 , (7.2.6) ¥к=тяь(ї*~). (7.2.7) де ск Набори величин {ск} і {ц/к} залежать від . їх називають, відповідно, амплітудним і фазовим спектром функції Д0. У фізиці спектри функцій широко застосовують. Наприклад, на основі комбінації амплітудного і фазового спектрів можна дослідити стійкість динамічних процесів. При моделюванні динамічних режимів фізичних систем, на основі амплітудного спектра вихідного сигналу можна оцінити коефіцієнт його нелінійних спотворень. Графіки залежностей ск і 1//к від є дискретними. їх зображають на площині (м?,С ) відрізками ліній, які розташовані перпендикулярно до осі абсцис у точках, кратних VI/. Наприклад, для функції Ґ0, -ТР/2<(<-ТР/4 /Сі)=<а, -ТР/4<і<ТР/4 , (7.2.8) 0, ТР І4<ї<ТРІ2 графік якої зображено на рис. 7.2, амплітудний спектр набуде вигляду, як на рис. 7.3.
424 7.2. Спектральний аналіз періодичних сигналів А £_ і -1У/2 - ТР/4 0 ТР/4 ТР/2 37Р/4 Рис. 7.2. Графік функції 2а/л 2а/3п 2а/5л О) о (О 3(0 3(0 Рис. 7.3. Амплітудний спектр функції Примітки. 1. Якщо значення періоду ТР збільшувати, то частота м> зменшується і густина ліній зростає. При ТР->ао дискретний спектр стає неперервним і ряд Фур’є переходить в інтеграл Фур’є. 2. У спектрі функції (7.2.8) відсутні парні гармоніки (їхні амплітуди дорівнюють 0, оскільки функція (7.2.8) є парною). Виходячи з поняття визначеного інтеграла і властивості парності чи непарності функції, можна довести, що для парних функцій (^0=/(-0) ряд (7.2.1) містить тільки косинусні гармоніки, а для непарних (/(0=-/(-0) - тільки синусні [6]. 7.2.1. Методичні вказівки Інтеграли (7.2.2), (7.2.3) і (7.2.4) обчислимо, застосовуючи Ьі-аі ТР формулу правих прямокутників. Позначимо через А = = — Ие Ие - крок дискретизації функції /(І) на періоді ТР. Дискретизацію виконаємо шляхом табулювання заданої функції, використовуючи варіант КЬ = 2 у ГП (див. рис. 7.1). Тоді в масив Хе будуть записані дискретні значення аргументу /,=аі+і-к, (тобто ХЄі=аІ+і-}і), а в масив Уе - дискретні значення функції /(і■ Уі) (і=0,1,...№-1). Враховуючи сказане, із виразу (7.2.2) одержимо: Л Ие-1 ■) Ие-І -у N6-1 а0=— У /(і • Л) • Л=— У /(і ■ к)=— У Ге, Відповідно (7.2.9)
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 425 у Ие-1 у Ие-1 ак=4-^Яі-к)сж<к»'і-к)=—'£Ге,сю(к»-ХЄі) ; (7.2.10) № ~Ґ, М? У N6-1 о №-1 Ьк=~гг £ /(іхувт(к*-і • И)=— £ Ге,, зіпф* • Хе,.;. (7.2.11) А/е £ ІУе ~ Частинна сума членів ряду (7.2.1) (гармонік) набуде вигляду: МУ ^,.=^+£^Со^-Хе,;+^/«^-Хе,.;Л'=0,1,...,Ие-1. (7.2.12) ^ £=/ Блок-схему алгоритму розкладання періодичної функції в ряд Фур’є наведено на рис. 7.5. У ній позначені ідентифікаторами 5, Є і І) - проміжні змінні дійсного типу. Для оптимізащї обчислень в алгоритмі введено змінну КОМ дійсного типу, у якій, за обчислення виразів (7.2.10) і (7.2.11) (блоки 5-8), поза цикл винесено значення к-м>, а за обчислення виразу (7.2.12) (блоки 20- 28) у циклі по к послідовно формуються значення к-й, де В=Хеі •и'. Результатом роботи алгоритму є обчислення та виведення на дисплей коефіцієнтів а0, ак,Ьк, амплітудного спектра ск, і формування N6 значень масиву які обчислені відповідно до виразу (7.2.12) для точок Хеі, і=0,1,2,..Ие-І. Завдання для самостійної роботи 1. Отримати функцію для дослідження і запрограмувати її як І>а5са/-функцію (рис. 7.4). 2. Згідно з алгоритмом (рис. 7.5) запрограмувати Разсаі- процедуру обчислення ряду Фур’є, вхідними параметрами якої слугують масиви Хе, їе і число Ие, а вихідним параметром - масив Yg. Щодо цього масиви А, В значень коефіцієнтів виразу (7.2.12) і масив С значень амплітудного спектра доцільно описати як локальні масиви дійсного типу розміру [0.. 20] цієї процедури. 3. Для різних значень з діапазону [3..20] і з діапазону [100..600] побудувати графіки залежностей Уе(Хе) і ЩХе). 4. Пояснити одержані результати.
426 1.2. Спектральний аналіз періодичних сигналів 5. Додатково до п. 1, 2, 3 і 4 побудувати графік залежності спектра Ск від уу (аналогічно до рис. 7.3). т- Р' Ю-(2-ТР-4^)/ТР, 4<2 ‘(і-ТР)/ТР, 0< г<ТР/2 ТР/2їі<3-ТРІ4 3‘ТР/4їі<ТР 4-£г/7Р, /(0 = і<2(2ГР-40/П?, I 4 <2{ї-ТР)ІТР9 0<і<ТР/4 ТР/4<і<3-ТР/4 3-ТР/4<1<ТР
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 427 7.2.2. Алгоритми побудови і табулювання ряду Фур' є Рис. 7.5. Алгоритм розкладання періодичної функції в ряд Фур’є
428 1.2. Спектральний аналіз періодичних сигналів 7.2.3. Процедура побудови і табулювання ряду Фур' є Procedure Fur je (Хе,Ye: Vector;Ne: Integer; Var Yg: Vector) ; Var a, b, c : Array[0..40] of Real; i, k, Ng :Integer; w, KOM, 3,0,0 :Real; Begin Write('Введіть кількість гармонік Ng= ’)/ Readln (Ng) ; TP := bl - al; w := 2 * Pi / TP; For k := 1 to Ng do Begin KOM := k * w; G := 0; D := 0; For i:=l to Ne do Begin s := KOM * Xe[i] ; G := G + Ye[i] * Cos (S) ; D := D + Ye [i] * Sin (S) End; a[k] := 2 * G / Ne; b[k] := 2 * D / Ne; c[c] := Sqrt (Sqr (a[k] + Sqr (b[k])) End; a[0] := 0; ' For I := 1 to Ne do a[0] := a[0] + Ye[i]; a[0] := a[0] / Ne; For і := 0 to Ne - 1 do Begin* S := 0; D := Xe[i] * w; For k:=l to Ng do Begin Xх KOM := k *d; S := S + b[k] * Sin (KOM) + a[k] * Cos (KOM) End; YG[i] := a[0] + S End End;
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 429 7.3. Інтерполювання Постановка задачі. Маємо деяку функцію у(х), яку задано у формі таблиці на скінченному проміжку [аі, Ь1\, тобто відомі значення .у, цієї функції у деяких Ие точках хі (/ = 0.№ -1) цього проміжку. Ці № значень можна отримати або під час експерименту, або шляхом вимірювань чи аналітичних обчислень. Як побудувати функцію /(х), яка в межах проміжку [я/, Ь1\ збігатиметься із функцією у(х) у точках хі. Точки хі називають вузлами інтерполювання або вузлами сітки. Функцію Дх) називають інтерполянтою. Мета інтерполювання - отримати ефективний алгоритм обчислення значень /(х) для будь-яких значень хє[аІ, 6/], які не збігаються з вузлами інтерполювання. Основні питання. Як побудувати /(х) і як оцінити похибку інтерполювання [84]: Щх)=у(х)-/(х) . (7.3.1) У фізиці інтерполювання застосовують у таких випадках: 1. З метою обробки результатів фізичного експерименту, щоб отримати і проаналізувати аналітичний вираз функції, що відповідає процесу, який досліджується. 2. З метою побудови наближених формул, які із заданою точністю відтворюватимуть результати обчислень за дуже складними формулами. 3. З метою згущення таблиць, коли отримано незначну кількість експериментальних значень за потреби мати їх більше. 4. Під час розв’язування задачі оберненого інтерполювання, яка полягає в обчисленні значень аргументу за відомими значеннями функції, заданої табличним способом. Інтерполяційні методи використовують також для обчислення похідних, для побудови формул чисельного інтегрування диференціальних рівнянь, для графічної обробки експериментальних результатів тощо. Зазвичай, інтерполянти будують як лінійні комбінації деякого набору т базових функцій: т-1 (7.3.2) і=0
430 7.3. Інтерполювання де (рі(х) - лінійно незалежні функції, а кі - невідомі досі коефіцієнти. Залежно від типу базових функцій, інтерполювання буває тригонометричним, експоненціальним;; поліноміальним тощо. Із умови збігу /(х) і у(х) у вузлах інтерполювання можна побудувати систему лінійно незалежних рівнянь і, наприклад, методом Гауса визначити шукані коефіцієнти кі. 9 т Якщо {фі(х)} - степеневі функції: 1,х,х ,...,* , то ми одержимо систему рівнянь з матрицею, визначник якої є визначником Вандермонда [93]. Відомо, що він не дорівнює нулеві. Тому коефіцієнти кі можна визначити однозначно. З математичного аналізу відома теорема Вейєрштраса [32]: Якщо функція у(х) є неперервною на проміжку [я/, ЬІ\9 то яке б мале не було додатне число є, знайдеться поліном Ьт(х) достатньо високого степеня т=і//(є), абсолютне відхилення якого від даної функції у(х) на проміжку \аІ, Ь1\ буде меншим від є, тобто для всіх точок хе [а/, Ь1\ виконається нерівність: \у(х)-Ьт(х)\<є. (7.3.3) Якщо функція у(х) сама є поліномом степеня т, то в кожній точці проміжку [а/, Ь1\ простежуватиметься тотожний збіг значень Ьт(х) і у(х). У загальному випадку різниця у виразі (7.3.3) є похибкою інтерполювання (7.3.1). Теорема Вейєрштраса, засвідчуючи існування єдиного при заданому виборі вузлів інтерполювання многочлена, не зазначає способу його побудови. Відомо кілька способів побудови інтерполяційного полінома: у формі Лагранжа, Ньютона, Бесселя, Стерлінга, Гауса тощо. Вибір форми тут визначається необхідною точністю, допустимим часом обчислень та ін. Ступінь складності побудови інтерполянти залежить від кількості вузлів і від того, чи ці вузли є рівновіддаленими, чи ні. Розрізняють глобальне і локальне інтерполювання. У глобальному випадку інтерполяційний поліном будують за всіма експериментальними точками. У локальному випадку для побудови інтерполянти беруть, в околі аргументу інтерполювання, таку кількість експериментальних точок, якої є достатньо для обчислення інтерпольованого значення із заданою точністю.
7.4. Дослідження інтерполяційного полінома Лагранжа Якщо відстань між вузлами’різна, то найчастіше використовують поліном у формі Лагранжа. Пояснимо принцип його побудови. Нехай маємо набір Ие різновіддалених експериментальних точок {ХеІ ,Уе,}, (/ = 0,Для двох суміжних точок з координатами (Хе0, Уе0) і (Хе1, Уех) можна побудувати поліном Лагранжа першого степеня (формулу лінійного інтерполювання): Іо! (х) = Х~ХЄі • Уе0 + -Х-~ —о_, у (7 4 4) Хе0-Хе1 0 Хеі-Хе0 1 Аналогічно, для точок (Хех, Уе1) і (Хе2, Уе2 ): А / \ ^ Хє^ хг х Хє\ . .. (х) = . Уех + 1— ■ Уе2. (7.4.5) ’2 Хех -Хе2 1 Хе2-Хех 2 Для трьох точок з індексами 0, 1 і 2 можна побудувати інтерполяційний поліном другого степеня (формулу квадратичного інтерполювання): І012(Х)= , (х-Хе0Хх-Хе2) ' ■ (Хе0-Хеіххе0-Хе2) (Хе, -Хе0)(Хе, -Хе2) [ (х-Хе.Хх-Хе,) п (Хе2 -ХЄ0)(ХЄ2-ХЄ]) 2~ Для Ие точок отримаємо поліном (А/їе -7)-го степеня: Ие-1 Ие-1 X-Хе Іл>Л...Ме-і(х) = Е ¥еі ■ П у. _ур , (7.4.7) /=0 у=0 леі ле] який називають поліномом Лагранжа для нерівновіддалених вузлів. 7.4.1. Методичні вказівки Завдання полягає у побудові Ря$ся/-функції І_ь, яка на основі експериментальних значень, за виразом (7.4.7), обчислює для кожного заданого х, значення ,у(х) = Ац,...м?-і(х) • За багаторазового використання формули (7.4.7) для одного і того самого
432 7.4. Дослідження інтерполяційного полінома Лагранжа набору експериментальних значень доцільно її обчислення розділити на дві частини: постійну, яка не залежить від х, а лише від експериментальних значень; змінну, яка залежить від х. У зв’язку з тим в алгоритмі одноразово формується масив дійсних значень КР розміру №, /-ту компоненту якого обчислюють за виразом: Блок-схему алгоритму побудови інтерполяційного полінома Лагранжа, згідно з виразами (7.4.8), (7.4.9) подано на рис. 7.7. У головній програмі хіо^ЬаЬ.рав на місце, яке відповідає блокові ЗО (див. рис. 7.1), поміщається виклик процедури з іменем ЬАвнмкз (рис. 7.6) табулювання полінома Лагранжа (тобто локальної для процедури ЬАвныгс функції і_ь). Перед викликом цієї процедури у блоці 29 головної програмі відбувається занулення ключа кь. Отож, за першого виклику функції і_ь, блоками 2-11 (рис. 7.7) одноразово формується масив КР. Після цього у блоці 12 значення кь встановлюється рірним 1 і, за наступних звертань до функції і_ь, обчислення відбувається лише згідно з блоками 13-24. У результаті Л^г-разового виклику функції і_ь процедура ьаэнмкз формує вихідні масиви Xg і Yg результатів інтерполювання. Увага! Оскільки значення і Ш не співпадають, як це було у випадку програмування ряду Фур’є, для Лагранжа і подальших алгоритмів необхідно у програмі хіо_(ЮЬ_Р1Юв замінити оператори: МотгеТо(Коипгі (Кх*Хе[0] + гх) ,Яоипсі(Ку*Уд[0] + гу) ) ; Гог і := 0 Ьо Ыдг - 1 <Зо Іі±пеТо{ІІоип<і (Кх*Хе[і] + Zx) ,Round(Ky*Yд[±] + гу) ) ; на MbveT'o(Round (Кх*Хд[0] + гх) ,Кошкі(Ку*Уд[0] + гу) ) ; Гог і : = 0 Ьо Ыдг - 1 do XineГo(Round (Кх*Хд[і] + гх) ,Лои^(Ку*Уд[і] + гу) ) Ие-1 (7.4.8) Тоді Ие-\ Ие-1 / «=Ц>хм (х)= £ КР, • П (*■-■)■• (7.4.9) /=0 у=0 і*]
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 433 Вхід Рис. 7.6. Алгоритм табулювання полінома Лагранжа |— із— 5=0 Рис. 7.7. Алгоритм побудови інтерполяційного полінома Лагранжа
434 7.4. Дослідження інтерполяційного полінома Лагранжа Завдання для самостійної роботи 1. Сформувати з допомогою NUMERI текстовий файл, який містить результати табулювання заданої викладачем тестової функції. Для отримання нерівномірної сітки необхідно будь-яким текстовим редактором знищити декілька рядків цього файла, які не стоять поряд, і записати відкоректований файл на диск. Наприклад, беремо число точок 15 і стираємо 5 несуміжних рядків файла. Тоді у головній програмі вводимо Ne = 10. 2. Створити на диску окремим файлом з назвою I_L.pas Pascal-^ункщю l_L згідно з алгоритмом рис. 7.7. 3. Запрограмувати PascaZ-процедуру lagrang табулювання полінома Лагранжа (рис. 7.6), вхідними параметрами якої слугуватимуть числа аі, Ы і Ngr, а вихідними - масиви Xg і Yg. Записати її на диск окремим файлом LAGRANG.pas. Після розділу опису її локальних змінних помістити директиву компілятора {$l l_L. pas} для під’єднання i_l як локальної функції цієї процедури. 4. Для різних значень Ne з діапазону [5..20] і Ngr з діапазону [100..600] вивести графіки залежностей Ye=f(Xe) і Yg = <p(Xg). 5. Дослідити похибку інтерполювання поліномом Лагранжа. З цією метою: • після 'виконання п. 1, 2, 3 і 4 змінити у процедурі LAGRANG оператор: Yg[i]:=I_L(Xg[i]); на оператор Yg[і]:=I_L(Xg[і])- f(Xg[i]);, де f - ім’я аналітичної функції, використаної при створенні текстового файла в NUMERI; • від’єднавши у головній програмі процедуру виведення графіка Ye = f (Хе), вивести графік залежності Yg = V (Xg) (графік похибки інтерполювання). 6. Пояснити одержані результати.
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 435 7.5. Локальне інтерполювання за методикою Ейткена Поліноми у формі Лагранжа є зручними для застосування, якщо відстань між вузлами різна, а кількість експериментальних значень невелика (№ < 20). Якщо ця кількість є значно більшою, необхідно застосовувати методи локального інтерполювання. Най- відомішим із них є ітераційний метод Ейткена [84]. Нехай маємо набір експериментальних даних {Хе:, Уеі} і =0,1,. . .^Л/с-1, для якого потрібно побудувати інтерполяційний поліном Лагранжа Ь од,..,№-і(х) • Легко переконатись, що поліном першого степеня Іод(х) можна записати: Ь01(х) = х- Хе* х—Хе 0 Уе0 х-Хе1 Уе1 Хе, —Хеп Аналогічно Ь12(х)= х-Х^ Уві х-Щ ЇЄ2 -^2,3 (х) — Увп х - Хе-, Уе-, Л?2 Тоді поліноми другого степеня набудуть вигляду: х-Хе0 Іод х - Хе0 Іод X — Хе 2 Ьу2 ■ > А,2,з(Х) X Хє>2 2 0 1 3 Хе^ Хє^ Відповідно, поліном Лагранжа степеня к матиме вигляд: X Хе0 Ц)Х...,к-1 х-Хек Ь2 к Хе к Хе0 (7.5.1) Якщо необхідно для деякого значення X € [аі, Ь1\ із точністю є проінтерполювати експериментальні результати {Хеі, Уе1}, це роблять так. Починаючи із формули лінійного інтерполювання, нарощують степінь інтерполяційного полінома і закінчують обчислення за умови: І 1о,і,2,...,к(х) - ьо,і,2,..„к-і(х) І<г,де 2<к<Ме-1. (7.5.2) Шукане проінтерпольоване значення обчислюють за формулою
436 7.5. Локальне інтерполювання за методикою Ейткена 7.5.1. Методичні вказівки Методику Ейткена побудови полінома Лагранжа доцільно запрограмувати як три окремі модулі: 1) функції Eit, яка реалізує вираз (7.5.1); 2) функції І_Е, яка реалізує власне ітераційну процедуру Ейткена (рис. 7.9); 3) процедури EITKEN, яка шляхом табулювання функції і_е формує вихідні масиви даних - результатів інтерполювання (див. алгоритм, що нарис. 7.8). Ря$ся/-функцію Eit, яка здійснює обчислення згідно з виразом (7.5.1), можна написати так: Function Eit (N, М: Integer; Y; Vector; x; Real) : Real; Begin Eit := ((x-Xe[N])*Y[N+1]-(x-Xe[M])*Y[N])/(Xe[M]-Xe[N]) End; З використанням цієї функції легко написати ітераційну процедуру Ейткена, що реалізує алгоритм, який зображено на рис. 7.9. Алгоритм використовує робочий масив L дійсного типу розміру [O.JVfe-l], який спочатку, окрім елемента L0, заповнено значеннями {Yef} (див. блоки 2-5 рис. 7.9). В L0 блоком 1 (рис. 7.9) записують значегійя, обчислене за поліномом L01(x) . Подальша робота алгоритму полягає у рекурсивному формуванні на основі елементів масиву L, значень Lj 2(х), L012(х) тощо і їхньому записі у відповідні елементи масиву Z, починаючи з Lj (див. блоки 7-10 рис. 7.9). У цьому випадку в елемент L0 почергово перезаписують значення, обчислені за виразом (7.5.1) для к = 2,3,... Jfe-T (згідно з поліномом Лагранжа k-то степеня). Разом з цим, блоком 11 формуються і записуються в робочу змінну G значення, обчислені із використанням полінома Лагранжа (£+1)-го степеня. Логічний блок 12 перевіряє умову (7.5.2) і, в разі її виконання, закінчує роботу алгоритму. Інакше відбувається перезаписування значення G в елемент L0 і продовження роботи алгоритму. Якщо задати таку високу точність є, за якої умову (7.3.3) неможливо виконати з використанням усіх експеримен¬
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 437 тальних значень, то алгоритм працюватиме як “чистий” алгоритм Лагранжа. Алгоритм, який ми пропонуємо, завжди будує послідовність поліномів L01(х), L! 2(x) , L012(х) і т. д., починаючи зі значень, які розміщені з лівого боку проміжку [аі, Ь1\. З погляду мінімізації похибки обчислень доцільніше для побудови цих поліномів обирати експериментальні значення з такими індексами, щоб аргумент інтерполювання х завжди перебував посередині цього набору значень з цими індексами. Проте такий алгоритм значно складніший для реалізації, ніж алгоритм рис. 7.9. Завдання для самостійної роботи 1. Сформувати з допомогою пакета NUMERI текстовий файл, який містить результати табулювання з нерівномірною сіткою заданої викладачем тестової функції. 2. Створити на диску файл EIT.pas, який містить функцію Eit, і файл I_Epas, що містить функцію І_Е, написану за алгоритмом на рис. 7.9. Масив L, змінну дійсного типу G і цілочисельні змінні і, j, к необхідно описати як локальні змінні цієї функції. 3. Використовуючи і>а5са/-процедури LAGRANG, створити процедуру табулювання функції І_Е, вхідними параметрами якої є числа al, bl і Ngr, а вихідними - масиви Xg і Yg (рис. 7.8). Записати її на диск окремим файлом EITKEN.pas. У ній доцільно помістити директиви компілятора {$1 ЕІТ.раз} і {$1 і_Е.раз) для під’єднання функцій Eit і і_е як локальних функцій цієї процедури. 4. Для різних значень Eps з діапазону [0.1 - 0.00001], -Ne з діапазону [5..20\ і Ngr з діапазону [100.. 600\ вивести графіки залежностей Ye=f(Xe) і Yg=ę(Xg). 5. Дослідити похибку інтерполювання поліномом Лагранжа, який побудовано за методикою Ейткена. З цією метою, після виконання п. 1, 2, 3 і 4 виконати зміни у процедурі EITKEN, аналогічні до описаних у завданні до Лагранжа. Побудувати графік похибки інтерполювання. 6. Пояснити одержані результати.
438 7.5. Локальне інтерполювання за методикою Ейткена ґ Вихід Л V й ) Рис. 7.8. Алгоритм табулювання Рис. 7.9. Алгоритм побудови полінома Лагранжа полінома Лагранжа, побудо- за методикою Ейткена ваного за методикою Ейткена
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 439 7.5.2. Процедура табулювання полінома Лагранжа, побудованого за методикою Ейткена Procedure Eitken (а 1, bl: Real; Ngr: Integer; Var Xg,Yg: Vector) ; Var і : Integer; hg, Eps : Real; {$1 I_E.pas} Begin Write('Введіть точність Eps='); Readln(Eps); hg := (bl - al) / Ngr; Xg[0] := al; For I := 0 to Ngr - 1 do Begin Yg[i] := IJE (Xg[i]); Xg[i + 1] := Xg[i] + hg End End; 7.5.3. Функція, яка будує поліном Лагранжа за методикою Ейткена (рис. 7.9) Function І_Е (х : Real) : Real; Var L : Vector; і, j, k : Integer; G i Real; ($1 EIT.pas) Begin L[0] := Eit (0, 1, Ye, x); For і := 1 to He do L[i] := Ye[i] ; For k:= 1 to Ne - 1 do Begin For j := k downto 1 do L [ j ] := Eit (j, k + 1, L, x) ; G := Eit(0, k + 1, L, x); If Abs(G - L[0]) < Eps then Begin I__E := G; Exit End; L[0]:=G End; I_E := G End End;
440 7.6. Дослідження інтерполяційного полінома Ньютона 7.6. Дослідження інтерполяційного полінома Ньютона Поліноми у формі Лагранжа застосовують, зазвичай, у випадку, коли є різна відстань між вузлами інтерполювання. Для рівно* віддалених вузлів існують простіші форми інтерполяційних поліномів, наприклад, поліноми Ньютона. Розглянемо правила їхньої побудови для задачі глобального інтерполювання. Нехай маємо набір експериментальних даних {Хеі9їеі}9 для якого необхідно побудувати інтерполяційний поліном /(х). Позначимо Хеі+1-Хеі=к, і = 0,1,...,Л^-1. Введемо поняття скінченних різниць. Низхідними скінченими різницями називають такі різниці: Д7е; = Уеі+1 - Уеі - скінченні різниці першого порядку; А2] порядку; Д*3 порядку. А2їеі = Аїем - АУе{ - скінченні різниці другого У\ АкУеі;= Ак~1Уеі+1 - Ак~1Уеі - скінченні різниці £-го х- Хе Позначимо: (2 = . Звідси х = Хе0 + 0-к . Тоді: к ~ х-Хвл х-Хе0-к „ Л - = = оскільки Хех=Хе0+к. к к Продовживши аналогічно, отримаємо ——^Єме~1 = Q-Ne +1. к Використовуючи введені позначення, інтерполяційний поліном записують так: КУр Л2Ур дММу- (7.6.1) Його називають поліномом Ньютона для інтерполювання вперед і застосовують для інтерполювання на початку проміжку. Наприкінці проміжку використовують поліном Ньютона для інтерполювання назад, який будують із використанням висхідних скінчених різниць: УУе, = їеі - - скінченні різниці першого порядку;
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 441 У2Уе = УУ<?( - Vїе._х - скінченні різниці другого порядку; У*Уе. = Vа'1 Уі?. - У^'Уе - скінченні різниці к -го порядку. Найзручнішим для програмування є поліном, який будують з використанням центральних (або розділених) скінчених різниць [85]. Першою центральною скінченною різницею називають вираз: їеі-їеі РВВІХе,^]= ' ; . 1 Хеі - Хе і Друга центральна скінченна різниця - це вираз: тпіу . ^ п И>0[Х*І,ХеІ]-П)0[Хеі,Хек] РВИ [Хе,,Хе ,Хек] = . Хе,~Хек т- та центральна скінченна різниця: ЯР , (7.6.2) З використанням таких позначень поліном Ньютона на основі центральних різниць записують так: їме-\(х) = ¥ео +РПО [Хеу,Хе0](х-Хе0)+ЕОО [Хе2 ,ХеьХе0](х-Хе0)(х-Хе])+... +ЕОО [Айдге-і ? Хе^_2,. ..,Хе$\(х—Хе0 X* ~ Хе1 )...(х—ХеМе_2) або скорочено: М?-1 к-1 ІИе-Лх)= ^ео + 21 • (7.6.3) /г=1 у=0 7,6.1. Методичні вказівки Завдання полягає у побудові Ра$са/-функції і_іт, яка на основі експериментальних значень, згідно з виразом (7.6.3), для кожного заданого хе[аІ, ЬГ\ обчислює значення /^е.і(х). При багаторазовому використанні формули (7.6.3) для одного і того ж набору експериментальних значень доцільно її обчислення розділити на дві частини: постійну, яка не залежить від х, а лише від експериментальних значень; змінну, яка залежить від х. Отож, в алгоритмі, за першого звертання до нього, одноразово формується матриця дійсного типу розміру (№ х ТУе), яка містить центральні скінченні різниці, що обчислюють ЗГІДНО 3 Шфімим
442 7.6. Дослідження інтерполяційного полінома Ньютона (7.6.2). Наприклад, для Ne- 4 ця матриця має таку трикутну структуру: FDD [ХехХе0] FDD FDD [Хеъ,Хе2,ХеьХе0] Щ FDD [Xe2,Xel] FDD• • •[Хе$,Хе2,Хе1] ^ ^ ^ Ye, FDD [Хе^\е2] Л Блок-схему алгоритму, який реалізує цю функцію, зображено на рис. 7.11. У логічному блоці 1 відбувається аналіз значення змінної KL, яке при першому звертанні до функції l_N дорівнює 0 (див. блок 29 рис. 7.11), а при наступних звертаннях - містить 1 (див. блок 13 рис. 7.11). Блоки 2-5 формують перший стовпець матриці FDD, а блоки 6-12 формують решту її компонент. При виклику функції l_N з конкретним значенням аргументу х, блоками 13-18 обчислюється за виразом (7.6.3) проінтерпольоване значення функції. Алгоритм формує і запам’ятовує в одновимірному масиві L, дійсного типу розміру [O..Afe-І], послідовність значень поліномів Ньютона всіх степенів від першого до (Ne -1 )-го. За цим вектором, можна, задаючи точність є, організувати локальне інтерполювання для наборів даних з рівновіддаленими вузлами. Завдання для самостійної роботи * 1. Оскільки поліном у формі Ньютона працює на основі рівномірної сітки експериментальних даних, то формування масивів Хе і Ye можна виконати, використовуючи варіант KL = 1 або KL = 2 у XIO JLAB.pas. 2.3а алгоритмом рис. 7.11 запрограмувати Ра«са/-функцію i_n і записати її на диск у файл з назвою I_N.pas. Описати локальні дійсні масиви функції l_N: матрицю FDD розміру [1..20,1..20\ і вектор L розміру [0..19], а також змінні і, j, k - цілого типу і R дійсного типу. 3. Запрограмувати Р</5са/-процедуру newton табулювання полінома Ньютона (рис. 7.10.), вхідними параметрами якої слугують числа а/, Ы і Ngr, а вихідними - масиви Xg і Yg. Записати її на
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 443 диск окремим файлом NEWTON.pas. Розташувати у ній директиву компілятора {$1 l__N.pas} для під’єднання i_n як її локальної функції. 4. Для різних значень Ne з діапазону [5..20] і Ngr з діапазону [100..600] вивести графіки залежностей Ye=f(Xe) і Yg=cp(Xg). 5. Дослідити похибку інтерполювання поліномом Ньютона. З цією метою: • після виконання п. 1, 2, 3 і 4 змінити у процедурі NEWTON оператор Yg[±] := I_N(Xg[i]; на оператор Yg[i] : = i_N(Xg[i]) - f (Xg[i]);, де f - ім’я заданої аналітично функції, яку використано при табулюванні; • від’єднавши у XIO_LAB.pas процедуру виведення графіка Ye=f(Xe), побудувати графік залежності Yg=y/(Xg) для похибки інтерполювання. 6. Пояснити результат.
444 7.6. Дослідження інтерполяційного полінома Ньютона 7.6.2. Алгоритми побудови і табулювання полінома Ньютона Рис. 7.10. Алгоритм Рис. 7.11. Алгоритм побудови табулювання полінома інтерполяційного полінома Ньютона Ньютона
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 445 7.6.3. Процедура табулювання полінома Ньютона Procedure Newton(al,bl: Real;Ngr:Integer; Var Xg,Yg: Vector); Var і: Integer; hg, Eps : Real; {$1 I_N.pas} Begin hg := (bl - al) / Ngr; Xg[0] := al; For і := 0 to Ngr - 1 do Begin Yg[i] := I_N (Xg[i]); Xg[i + 1] := Xg[i] + hg End End; 7.6.4. Функція, яка будує поліном Ньютона Function I_N (x :■ Real) : Real; Var r FDD: Array [1..20, 1..20] of Real; L : Vector; i, j, k : Integer; R : Real; Begin If KL = 0 do Begin For i:= 1 to Ne - 1 do FDD[i, 1] := Ye[i - 1]; For j := 2 to Ne - 1 do For i :=1 to Ne-j + 1 do FDD[i, j] := (FDD[i + 1, j - 1] - FDD[i, j - 1]) / (Xe[i + j - 2]- Xe[i - 1]); KL := 1 End; R := 1; L[0] := FDD[1, 1]; For k := 1 to Ne - 1 do Begin R0 := R * (x - Xe[k - 1]); L[k] := L[k - 1] + R * FDD[1, k + 1] End; I__N := L [Ne] End;
446 7.7. Інтерполювання сплайнами 7.7. Інтерполювання сплайнами Інтерполювання експериментальних результатів многочленом Лагранжа чи Ньютона на інтервалі [аі, Ы] з використанням значної кількості інтерполяційних вузлів часто спричинює до поганого наближення, що пояснюється значним накопиченням похибок у процесі обчислень. Окрім того, внаслідок розбіжності процесу інтерполювання, збільшення кількості вузлів не обов’язково зумовлює підвищення точності. Щоб уникнути великих похибок, увесь інтервал [аі, Ы\ розбивають на підінтервали, замінюючи на кожному з них функцію f(x) многочленом невисокого степеня. Це називають кусково-поліноміальним інтерполюванням [85]. Одним зі способів побудови інтерполянти на усьому інтервалі [сії, Ь1\ є інтерполювання за допомогою сплайн-функцій. Сплайн- функцією або сплайном називають кусково-поліноміальну функцію, визначену на інтервалі [сії, Ы\, яка має на цьому інтервалі деяке число неперервних похідних. Слово “сплайн” (англійське spline) означає гнучку лінійку, яку використовують для накреслення гладких кривих через задані точки площини. Перевагою сплайнів перед звичайним інтерполюванням є, по- перше, їхня збіжність, і, по-друге, стійкість процесу обчислень. Розглянемо частковий, однак розповсюджений в обчислювальній практиці випадок, коли сплайн будується на основі многочлена третього степеня (кубічний сплайн). Нехай на інтервалі [al, Ь1\ задано таблично неперервну функцію f(x) . Введемо інтерполяційні вузли (сітку): аі = Хе0 <Хех <...<XeNe_2 <XeNe_x - Ы, і позначимо = /(Хе і), і = 0,Ne-1. Інтерполяційним кубічним сплайном, що відповідає функції f(x) , визначеної у заданих вузлах, називають функцію s(x), що задовольняє такі умови: 1. Накожному інтервалі [Xe^j, Хе;], i=l,Ne-l функція s(x) є многочленом третього степеня. 2. Функція s(x), а також її перша і друга похідні є неперервними на інтервалі [аі, Ы\.
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 447 3. У вузлах інтерполювання вона збігається із функцією /(х) : .у (Хе,) =/(Хе,), і =0, Ие-1. Останню умову називають умовою інтерполювання. Розглянемо один із можливих способів побудови інтерполяційного кубічного сплайна з(х) . З цією метою на кожному з інтервалів [Хеи, Хе,], і=1, Ие-І функцію 5(х)^і(х) шукатимемо у вигляді многочлена третього степеня: 5і(х) = а,+Ь,(х-Хе,) + ^(х-Хе,)2+^-(х-Хе,)3, 2 Ь ХеіЛ <х<Хе,, і = (7.7.1) де а, ,Ь, ,с, ,сі, - коефіцієнти, що підлягають визначенню. З’ясуємо зміст уведених коефіцієнтів. Маємо: */(*) = Ь, + с,(х - Хе,) + у(х- Хе,)2, 5,"(х) = сі+сіі(х-Хеі), 5;"(х)=<іі. Тому О, =5,(Хе,), Ь^в'^Хе,), сІ=з,"(Хе1), сі, =8,'"(Хе,). Оскільки інтерполянта, за означенням, збігається з вузлами інтерполювання (тобто 5,(Хе,) = /(Ач?,), / = 1,ІУе-1), одержимо: а, = /(Хе,), / = 1, ІУе — 1. Довизначимо, окрім того, а0 = /(Хе0) . Вимога неперервності функції $(х) спричинює до умов *ДХе,.) = 5І+1(Хе,.), і = 1, Ие- 2. Звідси, з огляду на вирази для функцій 5, (х), одержуємо, при і = 0, №-2, рівняння: = <*м + Ьм (х, - Хе,+1) + 5±(Хе, - Хе,+1)2 + ^-(Хе, - Хеі+1)3. Позначаючи Иі = Хег - Хе^, перепишемо ці рівняння так: Л,ЬГЩ-с,+^а,=Г,-/м, і = 1,Мг-1. (7.7.2) 2 о
448 7.7. Інтерполювання сплайнами Умови неперервності першої похідної (Хеі), ■ / = 1, № - 2, спричинюють до рівнянь: с,И - Цк ,2= Ьі - Ь/ = 2,Л/е-1. (7.7.3) З умов неперервності другої похідної одержуємо рівняння: СІІИІ=СІ-СІ_1,І = ЇШ=Ї. (7.7.4) Об’єднуючи рівняння (7.7.2)-(7.7.4), одержимо систему із З-Ие-З рівнянь відносно 3(№-1) невідомих Ьі} с(, <У,, і = 1,Ие-1 Два відсутніх рівняння можна одержати, задаючи ті чи інші граничні умови для $(х). Припустимо, наприклад, що функція /(х) задовольняє умовам /"(«/) = /"(ЬІ) = 0. Тоді природно вимагати, щоб ^(а/) = $"(&/) = 0. Звідси одержуємо: 5,' (ЛГе0 ) = 0, {ХеМе_х) = 0, тобто с?! - ! = 0, с„= 0. Зауважимо, що умова с,-</,/?, =0 збігається з рівнянням (7.7.4) при і = 1, якщо с0 = 0 . Отож, ми отримали замкнуту систему рівнянь для визначення коефіцієнтів кубічного сплайна: (7.7.5) И Д. = с, -ч;м, і = 1,Ие-1, с0 = сМе_х = 0, <7/76> <7-7-7> Переконаємось у тому, що ця система має єдиний розв’язок. Вилучимо з рівнянь (7.7.5)-(7.7.7) змінні Ьі9 сІі, / = 1, ТУе - 2 . Одержимо систему, що містить тільки сі9 і = \,Ие-2. Щодо цього розглянемо два сусідніх рівняння (7.7.7):
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 449 м 2 М 6 Віднімаючи від першого рівняння друге, одержимо: Ь, ~Ьі-х = \(ЬіСі+ Підставляючи знайдений вираз для 6, - А,_1 у праву частину рівняння (7.7.6), одержимо: Лс_„ с м?„ п ісі п ^ аі-і 3 я, - ^ *м .(7.7.8) Далі, з рівняння (7.7.5) одержуємо: А?4 =А/(С; -см). А/2-1^/-1 = А/-1 (С/-1 -с;-г) Підставляючи ці вирази у (7.7.8), приходимо до рівняння: /і ~ /і-1 -//-1 ~ /і-2 + 2(лм + А, )см + А,с, = 6 Л, /-1 Остаточно, для визначення коефіцієнтів сі , одержуємо систему рівнянь: V/-! + 2(Л /+ Н і+і)Сі + Л.+1 С/+1 = 6 /і+1~Л 1'' а. 1+1 л, (7.7.9) / — 1, N6 — 2, — с— 0. Внаслідок діагональної переваги система (7.7.9) має єдиний розв’язок. Системи із тридіагональною матрицею коефіцієнтів, на практиці розв’язують методом, який є значно оптимальнішим за метод Гауса. Його називають методом прогонки. За знайденими коефіцієнтами сі коефіцієнти і Ьі визначають за явними формулами: 15 7-451
450 7.7. Інтерполювання сплайнами (7.7.10) Ъ. = —с, - СІ, + А •^~1, і = \,№-1. ' 2 ' 6 ' к Отож, доведено існування единого кубічного сплайна, що відповідає умовам 1-3 і граничним умовам зп{аї) = $"(&/) = 0 . Блок-схему алгоритму обчислення коефіцієнтів кубічного сплайна, згідно із теорією, яку наведено вище, зображено на рис. 7.12. Ідентифікатором Ма позначено матрицю коефіцієнтів системи лінійних алгебричних рівнянь (7.7.11), з якої знаходять невідомі коефіцієнти сі9 і = 1,Л^-2. Вона є тридіагональною. Її структуру подаємо нижче: 2 (Ь+Ь) к, 0 иг 0 0 ^ьіе-г о К СШ-2 / \ / (7.7.11)
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 451 Рис. 7.12. Алгоритм обчислення коефіцієнтів кубічного сплайна
452 1.1. Інтерполювання сплайнами 7.7.1. Процедура обчислення коефіцієнтів кубічного сплайна: s[i] (х)=а[і]+Ь[і.]Мх-Хе[і])+с[і]/2*(х-Хе[і])л2 +d[i]/6*(x- Хе[і])л3 Procedure CubSpln(Xe, Ye: Vector; Ne: Integer; Var a, b, c, d: Vec); Type Matrix = Array [1. . 51,1. . 51] of Real; Var h, Y : Vec; Ma : Matrix; i, j : Integer; R, Q : Real; {$1 Progorika.pas} Begin Ne := Ne - 1; {Формування вектора різниць h і коефіцієнтів а [і] сплайна} For і := 1 to Ne do Begin h[i] := Xe[i] - Xe[i - 1]; a[i] := Ye[i] End; {Формування CJIAP з тридіагональною матрицею Ma і вектором правої частини системи Y для обчислення коефіцієнтів с [і ] сплайна} For і := 1 to Ne - 1 do For j := 1 to Ne -,1 do If i=j then Begin R := h[i]; Q :=h[i + 1]; Ma [i, i] «= 2 * (R + Q); Y[i] := 6*((Ye[i+l]-Ye[i])/Q-(Ye[i]-Ye[i-l])/R) End Else Begin Q := h[i + 1] ; Ma[j, i] := 0; Ma[і + 1, i] := Q; Ma[i, і + 1] := Q End; Progonka (Ma, Y, Ne-1, c) ; {Розв'язання GJIAP методом прогонки} c[0] := 0; c[Ne] := 0; For i:=l to Ne do{Обчислення коефіцієнтів d[i] і b[і]} Begin R := h[i]; d[i] := (c[i] - c[i-l]) / R; b[i] := R*c[i]/2 - Sqr(R)*d[i]/6+(Ye[i] - Ye[i-1])/R End End;
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 453 Рис 7.13. Алгоритм формування і табулювання кубічного сплайна
454 7.7. Інтерполювання сплайнами 7.7.2. Процедура табулювання кубічного сплайна Procedure Spline(Хе, Ye : Vector; Ne, Ngr : Integer; Var Xg, Yg : Vector) ; Var a, b, c, d : Vec; h, R : Real; i, j, L : Integer; {$1 CubSpln.pas) Begin CubSpln (Xe, Ye, Ne, a, b, c, d); L := 1; h := (bl - al) / Ngr; Xg[0]:= al; For і := 0 to Ngr - 1 do Begin YG[i] := a[L] + b[L] * (Xg[i] - Xe[L])+ c[L] * Sgr(Xg[i] - Xe[L])/2 + d[L]*Sgr(Xg[i] - Xe[L])*(Xg[i] - Xe[L])/6; Xg[i + 1] := Xg[i] + h; If Xg[i] > Xe [L] then L := L + 1 End END; 7.8. Метод прогонки Необхідно знайти розв’язок CJIAP A-x = b , (7.8.1) де А - квадратна тридіагональна матриця розміру (N* N), а х, Ь - TV-вимірні вектор-стовпці. Застосовувати до системи (7.8.1) звичайні методи розв’язку CJIAP недоцільно, оскільки для зниження затрат процесорного часу можна використати спеціальну структуру матриці А . Нагадаємо, що ці затрати для найекономні- шого методу розв’язку СЛАР - методу Гауса - становлять величи- N3 ну порядку —. Щодо систем рівнянь із тридіагональними матрицями ці затрати можна знизити до величини, пропорційної розмірові системи - N. Метод, який дає змогу це зробити, називають методом прогонки. Запишемо систему рівнянь (7.8.1) з тридіагональною матрицею у розгорнутому вигляді:
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 455 а\,\Х\+а\,2 х2 =Ь\ а2,\Х\+аг,гХ2+аг,іХз =Ь7 а і ,їх,.,+а і, іХі+а,, мХі = 6, О7-8-2) Яы -і, ы- гХы-2 + СІц-\, +#лм, мХм Ъы-1 Сій, ы-\Хц-\ + С1ы, ыХц ~Ьы Щоб не використовувати подвійного індексування елементів матриці А під час подальшого викладення ідей методу прогонки, введемо позначення: о, = -а, ;а/ ; =с, ;аІ>(+1 - -(і, . Тоді систему (7.8.2) можна записати так: СіХ] -<І\ Хг = Ь\ ~агХі+СгХг + (ІгХг = Ьг (7.8.2') -аіХі-\+СіХі+сІіХм = Ьі —Яы -\Хы-2 + Сы-\Хм-\~(2ы-\Хы Ъы-\ ~С1мХы-1+Сы Хн Ьы Зведемо матрицю А з перепозначеними елементами до трикутного вигляду, аналогічно до того, як ми це робили у методі Гауса. Невідомі компоненти вектора розв’язку Хі шукатимемо у формі: Хі = а/Х/+і + Р/ , (7.8.3) де а, і р, - невідомі нам досі коефіцієнти, які називають прогоночними. Щоб виразити їх через коефіцієнти а, Ь, с і сі підставимо вираз (7.8.3) у систему (7.8.2): -аі(аі-іхі + (Зм) + ахі - сі,■*,■+1 = Ьі .
456 7.8. Метод прогонки Розкриємо дужки і перенесемо у праву частину рівняння всі його члени, що не містять х,: -а,а,-іх,+с,х,=Ь,+ аД_,+хм Звідси: і/, Ь: + Сф, , = 2 *м + — • (7.8.4) Сі-Оі ам с,-^ам Порівнюючи вирази (7.8.3) і (7.8.4), одержимо: „ • і > с, -я,ам р=^,+д,Р,-і (785) с< - Вирази (7.8.5) є рекурентними формулами, які дають змогу обчислювати наступні за номером значення коефіцієнтів а, і р,, якщо відомі їхні попередні за номером значення. Тобто, визначаючи а, і р,, ми за виразами (7.8.5) визначимо решту значень а, і Р(, і = 2- N. Можна довести, що обчислення цих коефіцієнтів є аналогом зведення матриці А до верхнього трикутного вигляду, тобто виконання прямого ходу методу Гауса. Якщо б ми змогли обчислити Хд,, то на основі виразів (7.8.3) можна було б визначити ,хм_2^, здійснюючи тим самим зворотний хід методу Гауса. З останнього рівняння системи (7.8.2') знайдемо: с!л Ьх *1 = х2 + • Сі Сі Враховуючи вираз (7.8.3) при /=1, отримаємо: 4 . 0 аі = — / Рі= — (7.8.6) З останнього рівняння системи (7.8.2') і рівняння (7.8.3) при і = И-1 отримаємо: -ах + с х = Ь ; X ~а х = В . Звідси виділивши N N-1 N N N ? Л N-1 ^-1 N Г ^ X Іі/ і з обох рівнянь і додаючи отримані вирази, одержимо:
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 457 Ьм ~Qn%N п /\ - + РлМ +aN-lXN а N Позбудемось у сумарному виразі знаменника: Ьм ~смхм +%Р^Ч =0 . Звідси % = Ь* +ак.Ьл . с,у аиам-і Порівнявши цей вираз із виразом (7.8.5), побачимо, що *лг = Рлг • (7.8.7) Алгоритм методу прогонки подано на рис. 7.13. 1. За формулами (7.8.6) і (7.8.5) визначаємо а,, р,, і = І..И. 2. Потім, виконуючи зворотний хід, визначаємо із (7.8.4) (7.8.7) і (7.8.3) - х,.. 7.8.1. Процедура розв'язання СЛАР тридіагональної форми за методом прогонки Procedure Progonka (А: Matгіх; b: Vec; N: Integer; Var X: Vec) ; Var Alp, Bet : Vec; R : Real; і : Integer; Begin Alp[1] := - A[l, 2] / A[l, 1] ; Bet[1] := b[1] / A[l, 1]; For і := 2 to N-l do Begin R := A[i,і] + Alp[і - 1] * A[i, і - 1]; Alp[і] := - A[i, і + 1] / R; Bet [i] := (b[і] - A[i, і - 1] * Bet[і - 1]) / R End; X[N] := (B[N] - A[N, N-l] * Bet[N - 1]) / (A[N, N] + Alp[N - 1] * A[N, N - 1]); For і := N-l downto 1 do X[і] := Alp [і] * X [i + 1] + Bet [i] End;
458 7.8. Метод прогонки
7.9. Апроксимування методом найменших квадратів Якщо експериментальні результати отримано зі значною похибкою, зумовленою дією зовнішнього шуму, то часто виникає задача виокремлення корисного сигналу і представлення його у формі аналітичної функції. На відміну від задачі інтерполювання, де будують функцію, яка в вузлах інтерполювання збігається з експериментальними значеннями, при апроксимуванні виконують усереднення, тобто будують функцію у(х), графік якої проходить, у певному сенсі, якнайближче до експериментальних значень. У статистичному аналізі такий процес називають регресією [107]. Нехай маємо набір експериментальних даних {Хеі,Уеі}9 для якого необхідно побудувати апроксимуючу функцію у(х). Будуємо її як лінійну комбінацію деякого набору базових функцій {£, (*)}, (і = 0, І, 2 У(х) = ^0(х) + ^1(х) + ^2(х) + ... + ^т(х), (7.9.1) де кі - шукані коефіцієнти. Тоді величина - у(Хеі)-їеі є похибкою апроксимування в 7-й точці. Ідея методу найменших квадратів (МНК) полягає в тому, що коефіцієнти £, знаходять із умови мінімізації суми квадратів похибок є і: Е(к0,к1,...,кт) = ^(у(ХеІ)-¥еІ)2. (7.9.2) /=0 Умову мінімуму величини Е можна задати системою рівнянь: ^ = 0; ^ = 0; «- = 0. (7.9.3) N*-1 - Оскільки Е= Е (^оЯо(Хеі) + к\§і(Хеі) + -- + кт8п,(Хеі)-¥еі) » /=0 то умови (7.9.3) еквівалентні системі т +1 лінійних алгебричних рівнянь:
460 7.9. Апроксимування методом найменших квадратів дЕ ме-\ — = 21 [(к080(Хе,)+к1&(Хе,)+...+кт8т(Хе1)-¥е,)-§0(Хе1)] = 0 і=о яр №-\ — = 2 I [(^0(Лге,.)+/г1^1(Хе,.)+...+/гшят(Хе,.)-Ге,.)-^(Хе,.)] = О о /•=о /?£ М?-1 — = 2 2 №0я0№,)+А:1я1(ХЄ,.)+...+^т№,)-ГЄі).<?т(Хе,)]=О окт 1=о які в матричній формі можна представити так: Ие-І - Ые-\ Ые-1 І 5о2№) 2 &(*,)&(*,)••• 2 &№)&»№) /=0 /=0 /=0 Ые-\ Ые-1 Ые-1 . I ЯоС**)&№)- 2 гт_1(Аё,.)ят(Хе,) 2 (Хе,) ;=0 1=0 /=0 ' Ые-\ /=0 №-1 I лдад.ге, ;=0 (7.9.4) Особливістю системи (7.9.4) є те, що її матриця симетрична до головної діагоналі. Розв’язуючи систему (7.9.4), отримуємо шукані коефіцієнти функції у(х) . 7.9.1. Методичні вказівки У цій роботі за базові візьмемо степеневі функції {х°,х1 ,х2,...,хт }, тобто g0=l, £/=*, ...., ят=хт . Тоді систему (7.9.4), наприклад, для т=3 запишемо так:
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 461 Ne Ne-1 z^, 1=0 Ne-1 , Z Xef /=0 Afe-l _ Z Xef /=0 Ne-\ ZÄ, /=0 Afe-l 0 Z^,2 /=0 Afe-l ~ Z Afe, 3 /=0 Ne-1 „ Z Xef /=0 Afe-1 . Z Xef /=0 Afe-1 _ Z Xef 1=0 Afe-l . Z Xef i=0 Ne-1 . Z Xef /=0 iSfe-l - Z Xef 1=0 Afe-l zx?<4 1=0 ‘ Afe-1 . Z Xef /=0 Afe-1 . Z Xef r=0 iVe-l Zft/ /=0 Afe-l /=0 Afe-l ~ Z Ye r Xef /=0 Afe-l ~ ZYerXe3 i=0 (7.9.5) A* = J5. Завдання полягає у формуванні системи (7.9.5) для будь-якого т є [1..20], розв’язанні її щодо невідомих коефіцієнтів поліному kt і побудови графіків експериментальної та апроксимуючої функцій для візуального спостереження процесу апроксимації. Блок-схему алгоритму обчислення коефіцієнтів полінома степеня т, який здійснює апроксимування експериментальних даних (згідно з МНК), зображено на рис. 7.14. Алгоритм працює так. Спочатку будуємо систему рівнянь (7.9.5). З цією метою формуємо перший рядок (блоки 7-11) та останній стовпець (блоки 12-16) матриці А коефіцієнтів системи (7.9.5). Для обчислення сум, з яких будують компоненти матриці А, заповнюємо одиницями робочий масив Xs дійсного типу розміру [0 .Ne-І] (блоки 3-6). Формування перелічених компонент відбувається шляхом використання функції Sum, яка обчислює суму значень компонентів масиву Xs і процедуру step для обчислення степенів компонент масиву Хе. Мовою Pascal вони, відповідно, набувають такого вигляду: Function Sum (N; Integer; у: Vector) : Real ; Var і : Integer; s : Real; Begin s : = 0; For і := 0 to N - 1 do s := s + у [i] ; Sum : = s End;
462 7.9. Апроксимування методом найменших квадратів Procedure STEP (N:Integer; у:Vector; Var x:Vector); Var і:Integer; Begin For і := 0 to N - 1 do x [ і ] := x [і] * У[і] End; Структура матриці А дає змогу, обчисливши її перший рядок і останній стовпець, не обчислювати решту її компонент, а виконати розсилання обчислених значень у відповідні елементи матриці. В алгоритмі це робиться у два етапи циклами, які відповідають блокам 17-26 (розсилання першого рядка матриці) і блокам 26-34 (розсилання останнього стовпця, починаючи з другого його елемента). У блоках 35-43 аналогічно формується вектор правих частин В системи (7.9.5). У блоці 44 управління передається процедурі, яка, розв’язуючи систему (7.9.5), знаходить шуканий масив К коефіцієнтів апроксимуючого полінома. На рис. 7.15 зображено алгоритм, який, за коефіцієнтами к{ будує апроксимаційний поліном степені т, табулює його і заносить результати табулювання в масиви Xg, Yg. Завдання для самостійної роботи 1.3а алгоритмом на рис. 7.14 запрограмувати Pascal- процедуру aprox обчислення коефіцієнтів кі апроксимуючого полінома, вхідними параметрами якої є масиви Хе, Ye і число Ne, а вихідними - масив коефіцієнтів К і порядок полінома М. Описати її локальними змінними: матрицю А дійсного типу розміру (10*10) , одномірний масив В дійсного типу з кількістю елементів 7Q, масив XS типу Vector, а також робочі змінні цілого типу /, у, L, М\ МР1. Описати, як локальну, процедуру step і функцію sum, тексти яких наведено вище. Для розв’язання системи (7.9.6) використати процедуру gauss. 2. Згідно з алгоритмом на рис. 7.15 запрограмувати Pascal- процедуру aprtab побудови апроксимаційного полінома і його табулювання, вхідними параметрами якої є масив коефіцієнтів апроксимаційного полінома К, його степінь М і кількість значень вихідної змінної Ngr, а вихідними - масиви вихідних величин Xg і Yg.
7. МЕТОДИ ОБРОБКИ РЕЗУЛЬТАТІВ ЕКСПЕРИМЕНТУ 463 3. Ввести з клавіатури або з текстового файла N6=5 пар вхідних даних, які відповідають точним значенням функції у - х ^ і (або у-х ). Переконатись у тому, що коефіцієнти полінома кі обчислені правильно (у першому випадку - це: 0 0 1, у другому - 0 0 0 1). 4. Для різних значень Ие з діапазону [3..10] і з діапазону [100..300] ввести набори вхідних даних, які мають розкид значень аргументів щодо точних значень для перелічених функцій на 20-30% в обидва боки. Здійснити апроксимування цих наборів даних поліномами степені як нижчої за кількість N6, так і рівної цій кількості. Побудувати для цих наборів даних графіки залежностей їе = /(Хе) і Yg = ер(Д£). 5. Пояснити результати. Увага! У програмі ХЮ_(30Ь_РІЮ6 виклик процедури обчислення коефіцієнтів апроксимуючого полінома Архох і процедури табулювання цього полінома АрхТаЬ необхідно робити так, як показано нижче: Аргох(Хе, їе, Не, КР, КЬ) ; Гог і:=1іоКХ+1сіо КР[і-1] := КР [і]; АргТаЬСаі, Ь1, КР, КЬ, Идг, Хд, їд);. У наведеному фрагменті програми ідентифікатором КР названо вектор коефіцієнтів полінома, елементи якого обчислює процедура ЯрхТаЬ. У змінній кь знаходиться значення вибраного нами степеня апроксимуючого полінома.
464 7.9. Апроксимування методом найменших квадратів Рис. 7.14. Алгоритм обчислення коефіцієнтів Рис. 7.15. апроксимаційного полінома згідно з МНК Алгоритм побудо¬ ви і табулювання апроксимаційного полінома
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 8.1. Загальні принципи моделювання Моделювання слугує методом пізнання людиною навколишнього світу. Здійснюючи експерименти, теоретичні дослідження, навіть обговорювання власних дій і намірів, ми практично займаємось моделюванням. Цілі, завдання, засоби й методи моделювання у цих випадках значно відрізняються один від одного, проте загальна спрямованість залишається єдиною - одержання нового знання шляхом випробування (дослідження) моделі, що слугує замінником реального об’єкта дослідження. Спрощено моделювання можна розглядати як певний експеримент, об’єктом якого слугує або матеріальний аналог досліджуваного об’єкта, який має ту саму фізичну природу, що й досліджуваний об’єкт, або його знакова (математична) модель у формі математичних формул, співвідношень, рівнянь, де завданням моделювання є встановлення нових знань про об’єкти, що описуються цими співвідношеннями. Результатом розв’язування інженерних (прикладних) задач будь-якого рівня слугують, зазвичай, чисельні оцінки (параметрів пристроїв, процесів, технічних і економічних характеристик тощо), які є наслідком розрахунків, що здійснюються з наближеними початковими даними. Здебільшого, прикладні задачі зводяться до математичних задач, які розв’язують різноманітними чисельними методами. Послідовність розв’язування таких задач можна подати наступними етапами:
466 8.1. Загальні принципи моделювання 1) постановка задачі; 2) створення математичної моделі (формулювання задачі); 3) перевірка моделі на адекватність; 4) побудова розрахункової (обчислювальної) моделі, яка відповідає обраній математичній моделі; 5) виконання розрахунків за обраною обчислювальною моделлю за заданих (відомих) значень початкових даних; 6) аналіз одержаних результатів. Під час розробки будь-якої моделі необхідно чітко визначити об’єкт моделювання, ціль моделювання і засоби моделювання. 8.1.1. Типи моделей Фізичні моделі. Фізичною моделлю називають пристрій, який дає змогу досліджувати певну систему шляхом заміни досліджуваного фізичного процесу у цій системі подібним йому процесом тієї ж чи іншої фізичної природи. Фізичні моделі поділяють на натурні, масштабні та моделі-аналоги. Натурні моделі - це реальні фізичні системи чи їхні окремі частини. Загальним критерієм вибору класу чи виду моделі слугує мінімізація затрат ресурсів на отримання необхідної інформації про систему чи процес, при виконанні заданих обмежень на її точність і достовірність. Такий підхід обмежує сферу застосування натурних моделей. Характерним прикладом тут можуть слугувати авіаційні системи, до яких вибувають високі вимоги щодо надійності, що майже неможливо забезпечити абстрактним моделюванням. Тому виконують дослідження в польоті дослідних зразків літаків. Під час моделювання складних систем широко застосовують моделювання це всієї системи, а її окремих частин. Натурні моделі вирізняє цілковита адекватність реальній системі і зумовлена цим висока точність і достовірність результатів моделювання. Отож, зазвичай, процес проектування закінчується етапом натурних досліджень системи. У будь-якому випадку використовувати на ранніх етапах дослідження інші види моделей ніхто не забороняє. Масштабні моделі застосовують при дослідженні складних систем, для яких неможливо або складно зробити досить точний математичний опис їхнього функціонування, а натурних зразків ще не існує, або експерименти, що дають потрібні дані, провести з натурним зразком неможливо. Це стосується експериментів з
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 467 дослідження поведінки системи в екстремальних аварійних умовах. У цьому випадку досліджують модель тієї ж фізичної природи, що й досліджувана система, однак інших фізичних розмірів. Теоретичною основою масштабного моделювання є теорія подібності, яка передбачає дотримання геометричної подібності оригіналу та моделі і відповідних масштабів для їхніх параметрів. З цією метою реальні значення параметрів множать на постійну величину, яку називають масштабом моделювання або коефіцієнтом подібності. Умови подібності виконуються за рівності критеріїв подібності - безрозмірних величин, які є комбінацією фізичних параметрів моделі і досліджуваної системи. Масштабні моделі застосовують для моделювання аеродинамічних процесів, гідротехнічних споруд, багатьох технологічних процесів, для яких розроблено відповідні критерії подібності. Моделі -аналоги принципово відрізняються від натурних і масштабних моделей тим, що процеси досліджуваної системи вивчають на процесі-аналозі іншої фізичної природи. Обов’язковою умовою тут є виконання однозначної відповідності між параметрами об’єкта, що вивчається, і його моделі, яка виражається у тотожності безрозмірних математичних описів процесів, що відбуваються у них. Подібні величини, які характеризують процеси, відрізняються тільки масштабами. Отож, за характеристиками моделі можна однозначно визначити характеристики оригіналу. Аналогова модель є моделлю високого рівня абстрагування, оскільки для свого синтезу вона вимагає наявності математичного опису системи, що досліджується, тобто математичної моделі. Процесами-аналогами слугують механічні, гідравлічні, пневматичні процеси, проте, найширше застосування отримали електричні аналогові моделі. У цих моделях струм, напруга чи потужність слугують аналогами фізичних величин іншої природи. Такі моделі гнучкі, оскільки можна легко підлаштовуватись до кількісних змін параметрів модельованої системи. Це дає змогу створювати спеціалізовані моделі для моделювання широкого класу систем. Іншою принциповою відмінністю аналогових моделей є їхня байдужість до фізичної суті модельованого процесу за однакового їхнього математичного опису. Це дає змогу будувати структурні аналогові моделі, блоки яких на основі математичних рівнянь
468 8.1. Загальні принципи моделювання відтворюють окремі етапи процесу, а після їхнього об’єднання відтворюють увесь процес загалом. За принципами аналогового моделювання працюють аналогові обчислювальні машини. Математичні моделі (ММ). Необхідність у підвищенні узагальненості та універсальності моделей і методів моделювання вимагає підвищення рівня абстрагування. Щодо цього най- абстрактнішим, а, отже, найбільше узагальненим є символьний опис. Тут для опису системи вводять спеціальні символи і встановлюють правила оперування з ними. Сукупність символів і правил їхнього використання (граматика) є абстрактною мовою. Деяке твердження, записане на абстрактній мові, утворює формулу. Прикладами абстрактних мов слугують хімічні формули та математичні формули. Щодо цього математику можна трактувати як цілий клас абстрактних мов з різними граматиками і різними рівнями абстрагування. Відповідно до сказаного, математична модель - це система математичних співвідношень, яка описує певний фізичний процес чи явище. Для побудови ММ використовують будь-які математичні засоби - теорію множин, диференціальне та інтегральне числення, математичну логіку, теорію ймовірностей, теорію ігор і т. д. Вибір виду ММ визначають за метою моделювання, оскільки розгляд моделі на певному рівні дає змогу отримати відповіді на певну групу питань, а щоб отримати іншу інформацію - необхідна ММ іншого виду чи іншого рівня абстрагування. ММ поділяють на детерміновані і стохастичні. Перші встановлюють однозначну відповідність між характеристиками моделі, а другі - між статистичними параметрами її характеристик. Вибір того чи іншого виду моделі зумовлений ступінню необхідності врахування випадкових чинників. ММ також класифікують за методом їхнього дослідження на аналітичні, регресійні та імітаційні моделі. Аналітичні моделі дають змогу отримати або явні залежності для шуканих величин, або (у випадку, коли це не вдається) визначити чисельні розв’язки для конкретних початкових умов і кількісних характеристик моделі. Для розв’язання таких задач широко використовують комп’ютери. Проте синтез аналітичних моделей для значної кількості систем, зазвичай, є неможливий. Отож, сьогодні широко розповсюджене імітаційне моделювання, яке розглядають як експеримент зі складною моделлю, що описує
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 469 поведінку системи, яку можна реалізувати на ПК як модель реального експерименту. Регресійні моделі - це емпірично встановлені залежності (формули, диференціальні і різницеві рівняння, статистичні закони), які не претендують на розкриття механізму функціонування досліджуваного процесу загалом. Коефіцієнти у регресійних моделях, зазвичай, визначають за допомогою процедур ідентифікування параметрів моделей за експериментальними даними. Щодо цього найчастіше мінімізують суму квадратів відхилень теоретичної кривої від експериментальної для всіх точок вимірів. Імітаційні моделі володіють такими особливостями: великою розмірністю за кількістю змінних і зв’язків між елементами моделі; стохастичним характером; наявністю різних типів нелінійних обмежень; різним математичним описом елементів моделі; реакціями, що залежать від часу. Вони, зазвичай, максимально враховують наявну інформацію щодо складності системи. Імітаційне моделювання дає змогу: • експериментально досліджувати складні внутрішні взаємодії у досліджуваній системі; • вивчати вплив на функціонування системи імітаційних і організаційних змін та змін характеру взаємодії із зовнішнім середовищем; • ліпше зрозуміти систему, оцінюючи ієрархію змінних та їхню взаємодію; • оцінити поведінку системи в нових ситуаціях, перевірити нові стратегії та правила прийняття рішень; • здійснювати стохастичне моделювання, наприклад, методом Монте-Карло. Отже, імітаційне моделювання орієнтоване не тільки на дослідження заданої моделі, але й на ідентифікацію параметрів, Отож, воно є аналогом натурного моделювання. Імітаційні моделі застосовують у біології для опису об’єктів різного рівня організації живої матерії - від біомакромолекул до моделей біогеоценозів. В останньому випадку моделі налічують блоки, що описують як живі, так і “відмерлі” компоненти. Класичним прикладом імітаційних моделей слугують моделі молекулярної динаміки, у яких задаються координати й імпульси всіх атомів, що формують біомакромолекулу і закони їхньої
470 8.1. Загальні принципи моделювання взаємодії [27, 28]. Відома комп’ютерна програма “життя” дає змогу простежити, як системні фізичні закони проявляються у функціонуванні найпростіших біологічних об’єктів - біомакро- молекул і їхнього оточення. Подібні моделі, у яких елементами (цеглинками) слугують не атоми, а групи атомів, використовують у сучасній техніці комп’ютерного конструювання біотехнологічних каталізаторів і лікарських препаратів, що діють на визначені активні групи мембран мікроорганізмів, вірусів, чи виконуючих інші спрямовані дії. 8.1.2. Особливості ММ фізичних систем Термін математичне моделювання означає, що ми вчимось досліджувати не сам фізичний об’єкт, а його модель. Здебільшого, поведінку фізичних процесів і фізичних систем можна описати ММ у формі систем звичайних диференціальних рівнянь (ЗДР) або рівнянь у частинних похідних. Розглядатимемо лише перший випадок. Нагадаємо, що диференціальними рівняннями називають рівняння, у яких взаємозв’язані похідні від шуканої функції, сама шукана функція та незалежна змінна. Розв’язком диференціального рівняння називають функцію, що має необхідну ступінь гладкості, і яка, за умови підставлення її у диференціальне рівцяння, перетворює його в тотожність. Процес визначення розв’язку диференціального рівняння називають його інтегруванням. Якщо в диференціальному рівнянні невідомі функції є функціями однієї змінної Р(х,у,у\у", ... ,Ул)) = 0 , то його називають звичайним диференціальнимрівняннялі. Якщо невідома функція, яку налічує диференціальне рівняння, є функцією двох або більшої кількості незалежних змінних: ^ _дг дг д”2ч_л ’ А*. ’ А. ’ ”" ’ а. / а. к—1 ’ ” ’ а. я ^ — ’ дх ду дх,д/ ' ду то таке рівняння називають диференціальним рівнянням у частинних похідних.
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 471 Порядком диференціального рівняння називають максимальний порядок похідної від невідомої функції, що входить у диференціальне рівняння. Процес математичного моделювання певного фізичного об’єкта можна умовно поділити на три етапи: 1. Побудова його ММ як системи ЗДР у канонічній формі Тут х, /, Р - вектор-функції. 2. Розв’язання (інтегрування) рівняння (8.1.1) чи (8.1.2) на певному проміжку часу [ґ0, їк ], тобто визначення сім’ї кривих. Якщо задати початкові умови х(0) = хо, то матимемо розв’язання так званої задачі Коші [82, 89, 109]. 3. Дослідження (аналіз) розв’язку з метою отримання певних характеристик поведінки об’єкта. Оскільки існує чимало об’єктів, які досліджують фізики, то кожна предметна область має свій математичний апарат і свою методику побудови ММ своїх об’єктів. Розгляд методики побудови ММ якогось конкретного фізичного об’єкта не є нашим сьогоднішнім завданням. Окреслимо тільки базові ідеї, які тут використовують. Здебільшого, моделювання фізичних об’єктів можна виконати на мікро- чи на макрорівні. Ці рівні відрізняються ступінню деталізації розгляду процесів, які відбуваються в об’єкті. Математичною моделлю системи на мікрорівні слугує система диференціальних рівнянь у частинних похідних, яка описує процеси в суцільному середовищі із заданими крайовими або граничними умовами. Загальний вигляд таких систем рівнянь для кожного розділу фізики є добре відомим. Це рівняння Ламе у механіці пружних середовищ, рівняння Нав’є-Стокса у гідравліці, рівняння теплопровідності у термодинаміці, рівняння Лапласа і Пуассона у фізиці напівпровідників і т.д. Здебільшого, чисельним шляхом усі ці типи рівнянь розв’язують методами скінченних Коші: (8.1.1) або у неявній формі: . Р(х, х,0 = 0 (8.1.2)
472 8.1. Загальні принципи моделювання різниць або методами скінченних елементів. Унаслідок застосування цих методів одержують систему лінійних алгебричних рівнянь дуже високого порядку, яку не просто розв’язати навіть на сучасних швидкодіючих комп’ютерах. Отож, з метою пониження розміру системи необхідно робити певні спрощення. Математичні методи дослідження систем на мікрорівні вивчають у курсі “Методи математичної фізики”. Математичною моделлю фізичного об’єкта на макрорівні є система ЗДР із заданими початковими умовами. Її будують за компонентними рівняннями, що описують окремі елементи досліджуваного об’єкта, і топологічними рівняннями, які задають зв’язки між цими елементами. Топологічні рівняння значної кількості фізичних систем базуються на рівняннях рівноваги і рівняннях неперервності. Для електронних схем їх будують на підставі закону Ома і двох законів Кірхгофа. І закон Кірхгофа (рівняння рівноваги) ^7* = 0, де 7 - струм к що підходить до деякого вузла схеми, к - кількість вузлів схеми, без урахування заземленого. 77 закон Кірхгофа (рівняння неперервності) £{/*= 0, де ик к - спад напруги на к -му елементі будь-якого замкнутого контура схеми, к - кількість незалежних контурів. У механічних системах аналогом І рівняння Кірхгофа є принцип Даламбера ^^=0 - сума сил, які діють на тіло, к включно з інерційними, дорівнює нулю. Аналогом II закону Кірхгофа є’ рівняння, що виходить із принципу додавання швидкостей: = 0 . Абсолютна швидкість є сумою відносних і і переносних швидкостей. Сформулюємо головні вимоги до процесу побудови ММ фізичних об’єктів: 1.ММ повинна максимально чітко і вичерпно описувати закони взаємодії його елементів між собою, а також правильно враховувати реакцію об’єкта на зовнішні збурення. 2. До ММ застосовують вимоги точності, економічності та універсальності:
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 473 • точність - це характеристика моделі, яка полягає у найвичерпнішому якісному і кількісному відображенні нею дійсних властивостей об’єкта; • економічнішою буде та модель, яка для досягнення заданої точності вимагає менших затрат ресурсів комп’ютера; • під універсальністю ММ розуміють її застосовність до широкого класу об’єктів і зовнішніх збурень. Ми розглядаємо математичне моделювання процесів, які описуються системою рівнянь типу (8.1.1). Щодо цього функціональна залежність /(х,0> зазвичай, є нелінійною. Задачі механіки, гідравліки, теорії пружності, астрономії, радіоелектроніки зводяться до розв’язання системи виду (8.1.1). 8.1.3. Дискретизація рівнянь ММ Сформовану ММ досліджуваного об’єкта можна розв’язувати як аналітично, так і чисельно. Аналітично розв’язати задачу Коші можна лише у найпростіших випадках. Проінтегрувати систему (8.1.1), здебільшого, можна тільки чисельними методами. Отож, ми вивчатимемо лише чисельні методи розв’язання задачі Коші. Розглянемо спочатку простий випадок, коли математичною моделлю фізичного процесу слугує одне диференціальне рівняння. Нехай потрібно розв’язати задачу про радіоактивний розпад. Закон радіоактивного розпаду стверджує, що відношення кількості атомів, які розпались за будь-який малий проміжок часу, до кількості атомів, які існували на початку цього проміжку, не залежить від загальної кількості атомів (якщо ця кількість є доволі великою). Адже радіоактивний розпад - це розпад ядер, які у звичайному стані не взаємодіють між собою, оскільки взаємодіють лише електронні оболонки. Отож, імовірність розпаду атома не залежить від того, скільки є атомів. Очевидно, що кількість атомів, які розпались за малий проміжок часу А/1, є пропорційною А/. Позначимо масу речовини, що ще не розпалася в момент часу ґ, через х(0 . За час Аґ розпадеться х(0 - х(( + Аґ) речовини. Головний закон радіоактивного розпаду можна записати так: х(0-х(ґ + Ар ^ х(0
474 8.1. Загальні принципи моделювання Ця рівність стає все точнішою зі зменшенням проміжку М. Коефіцієнт к є постійним і характеризує радіоактивну речовину. Він дорівнює імовірності розпаду окремого атома за одиницю часу за умови вибору цієї одиниці достатньо малою порівняно з періодом піврозпаду цієї речовини. Перепишемо нашу рівність: х(ґ + А()-хи) , .. — - -&-кх(0. (8.1.3) Д? Оскільки точність цього рівняння зростає при Л? —> 0, то здійснюючи граничний перехід, отримаємо точну рівність: ^-=т=-ед, (8.1.4) ш яка є диференціальним рівнянням радіоактивного розпаду. Позначимо через х0 кількість радіоактивної речовини на момент початку спостереження, тобто х(0) = х0 .Це буде початковою умовою для рівняння (8.1.2). Якщо воно має єдиний розв’язок, то визначаючи цей розв’язок на проміжку часу [0,^], де ^ - кінцевий час дослідження, ми промоделюємо процес радіоактивного розпаду. З теорії диференціальних рівнянь відомо, що розв’язком рівняння (8.1.4) слугуватиме множина функцій. Обираючи певну початкову умову, ми знайдемо одну функцію х(ґ) з цієї множини. Проілюструємо, як це можна зробити. Розділимо рівняння (8.1.1) на х(ґ). Отримаємо: = (8.1.5) *(') За правилом диференціювання складної функції і, враховуючи, що (1пх)' = —, можна переписати рівняння (8.1.5) у вигляді: х (1п х(0У = -(ИГ. Оскільки дві первісні однієї функції відрізняються на постійну, отримаємо: 1п х(0 = -кґ Нг С,. Звідси, х(0 = е~кі+Сі = еСхе~кі = Се~кі, де С > 0 . Підстановка ґ = 0 дає: С = х0 . Ми отримали розв’язок диференціального рівняння (8.1.4) з початковою умовою х(0) = х0 :
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 475 х(0 = х0е к‘. (8.1.6) Розглянемо найпростіший чисельний метод (ЧМ) розв’язання задачі Коші, яка формулюється так: Знайти розв’язок диференціального рівняння на інтервалі [ґ0 , ], який задовольняє початкову умову х(/0) = х0 : У випадку системи диференціальних рівнянь розв’язок х(ґ) складається із множини функцій, які задовольняють вектору початкових умов х(ґ0) = хо . З теорії диференціальних рівнянь відомо, що задача Коші має єдиний розв’язок, якщо функція /(х,ґ) визначена і неперервна на інтервалі [/0, ік ] і задовольняє там умову Ліпшиця [89]: де Ь - скалярна величина, що зветься константою Ліпшиця. Вона є верхньою границею норми першої похідної вектор-функції Загалом чисельний розв’язок задачі Коші полягає у заміні цієї задачі її дискретним (різницевим) аналогом: Тут Аш+1 = іт+1 - ґт - крок інтегрування. Дискретний аналог (8.1.8) задачі Коші (8.1.7) отримуємо, застосовуючи до формули (8.1.1) один із методів чисельного інтегрування. У виразі (8.1.8) символом т позначено номер кроку інтегрування, а символ к визначає “кроковість” чисельного методу. Ця величина вказує на те, що інформацію к попередніх кроків інтегрування використовують у цьому ЧМ для обчислення значення хт+1. Відповідно, розрізняють однокрокові та багатокрокові чисельні методи. При заміні (дискретизації) виразом (8.1.8) задачі (8.1.7) з певною точністю повинні виконуватись умови якісної відповідності неперервної та дискретної моделей. Ці умови полягають у тому, що (8.1.7) ГУГ II / по змінній а: - (матриці Якобі) системи (8.1.7): — < Ь. • • • •
476 8.1. Загальні принципи моделювання задачі (8.1.7) і (8.1.8) повинні мати однакові стаціонарні режими та аналогічну структуру фазового простору. При розробці програм, які реалізують чисельні методи розв’язання задачі Коші, використовують поняття точності, стійкості, узгодженості ЧМ, локальної і глобальної похибки дискретизації, жорсткості, обумовленості. Поняття точність і стійкість різницевих схем стосуються вимоги досягти малого відхилення значень розв’язків рівнянь математичних моделей від їхніх точних рішень. Точність пов’язана з локальними похибками. Є два джерела виникнення похибок: • похибки заокруглення виникають внаслідок скінченної довжини комірок пам’яті комп’ютера, у які записують двійкові представлення дійсних чисел; • похибки дискретизації полягають у тому, що під час заміни неперервної функції її дискретним аналогом у вигляді рядів ми беремо не безмежну, а скінченну кількість членів ряду. Стійкість взаємозв’язана із процесом накопичення похибок. Навіть якщо похибки заокруглення і похибки дискретизації є малими, від обчислень буде мало користі, якщо вплив цих малих похибок з часом наростає, тобто розв’язок є нестійким. 8.2. Явний метод Ейлера % Розглянемо найпростіший ЧМ, який ми можемо застосувати для розв’язання ММ задачі про радіоактивний розпад. Для зручності запишемо його диференціальне рівняння ще раз: ^ = х'(?) = -ВД- (8.2.1) ш Якщо розв’язок цього рівняння має неперервні вищі похідні (хоча другу), то його можна розкласти у ряд Тейлора: і(,+*) = *(0+^+^!ЇМ+^!*М + ... (8.2.2) 1! 2! З! Якщо всі члени ряду (8.2.2), які містять похідні, що вищі за першу, відкинути, ми отримаємо чисельний метод розв’язання задачі Коші під назвою явний метод Ейлера (ЯМЕ). Перейшовши до дискретних відліків; часу, одержимо х(^) = х(ґ0) + И/(х(ґ0),ґ0) або у загальноприйнятому записі:
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 477 Хт+1 = Хт + ¥(Хт>'т) , (8.2.3) де А = ґт+1 - іт, т - номер дискретної точки. З метою дослідження властивостей ЯМЕ розглянемо інтегрування цим методом простого модельного диференціального рівняння: х = ^- = Лх(0, X(ґ0) = х0. (8.2.4) т Вище ми зазначали, що аналітичним розв’язком цієї задачі слугує функція х(ґ) - х0еЛі. Для аналізу впливу похибок на числовий розв’язок рівняння (8.2.4) проінтегруємо це тестове рівняння ЯМЕ з И=Соп&. Щоб відрізнити точний розв’язок рівняння (8.2.4) від чисельного розв’язку, який містить похибки, позначимо останній через и((), а наближене значення початкових умов у точці ? = /0 позначимо и0 [5]. Тоді: иі =ио +Ь/(х>0 = ио +ЬАи0 =и0(1 + кЛ) ; и2 =щ +кЛи1 =м1(1 + /гЯ) = м0(1 + ЛЯ)2; «т+1=«0(1 + МГ+1. Нехай початкову умову х0 введено у пам’ять комп’ютера з похибкою. Позначимо це наближене значення початкової умови через и0. Тоді величина е0 = х0 - и0 слугуватиме похибкою введення початкової умови. Вона може з’явитись або внаслідок “ручного” заокруглення числа при введенні х0, або внаслідок заокруглення під час запису числа у пам’ять машини, або внаслідок обох причин. Якщо порівняти вирази: их =м0(1 + АЛ) і х = х0еЬі =х0еЛк ; ит+1=и0(1 + ИА)т+1 іх = х0е(т+1)НЛ, то можна зробити висновок, що тут експонента апроксимована виразом (І + кХ), тобто у розкладенні експоненти у ряд Тейлора м , ИХ (ИХ)2 (ИХ)г еп/ь = 1 + — + ———к ———і-... було відкинуто всі доданки, починаючи з третього. Запишемо вираз для глобальної похибки, яка накопичиться до (пі +1) -го кроку інтегрування. Оскільки
478 8.2. Явний метод Ейлера Ит+1 =и0(і + /аг+1 =(*о -е0)(1 + А/ІГ+1, З останнього виразу бачимо, що у випадку застосування ЯМЕ до розв’язання задачі (8.2.4) глобальна похибка Ет+1 має дві складові: 1) похибка, яка виникає внаслідок апроксимації експоненти еих виразом (1 + йД); 2) похибка, зумовлена неточністю введення початкових умов *о- У випадку 11 + НА \ > 1 друга частина похибки Ет+1- е0(1 + ЛД)т+1 зростатиме зі збільшенням кількості кроків т і, врешті-решт, зведе нанівець весь процес інтегрування. Отже, якщо А < 0, то для того, щоб нейтралізувати частину похибки Ет+1> зумовленої наявністю е0, необхідно обирати такий крок И, при якому забезпечується виконання умови 11 + ИЛ | < 1, Це умова стійкості явного методу Ейлера! Оскільки значення Л характеризує задачу, то можна стверджувати, що оптимальний крок інтегрування Н необхідно обирати конкретно для кожної задачі. Величину, обернену до А, називають постійною часу. Її позначають г. Чим більше значення А, тим менше т і експонента розв’язку швидше загасає. Отож, для правильного відтворення інтегральної кривої необхідно, щоб значення величини кроку А було меншим. Приклад. Нехай у рівнянні (8.2.4) А = -10. Розв’яжемо з йх допомогою ЯМЕ це рівняння — = -10х з початковою умовою Ж х(0) = 1 на проміжку ґє[0,3]. Порівняємо розв’язки, одержані тобто: (8.2.5)
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 479 чисельним шляхом з різними кроками інтегрування, із аналітичним розв’язком цього рівняння X = е~ш. Результати цього порівняння подано на рис. 8.1, з якого 2 бачимо, що крок інтегрування А, який є більшим за — = 0.2, спричинює нестійкість. X 4г -2 А -0.05 И-0.17 И-0.2 і \ М / \ І \ і ! У7 *\ / \ / І \ / \ ! \ Рис. 8.1. Інтегрування модельного рівняння з різними часовими кроками 8.3. Методи Рунге-Кутта На початку XX століття Рунге, Хойн і Кутта запропонували підхід, заснований на побудові формули дискретизації рівняння (8.1.1) у вигляді: х»+і =хп+НФ^„,х„,Н). (8.3.1) Тут функція Ф є близькою до /, однак, не містить похідних від функції правої частини рівняння (8.1.1). Одержано сім’ю методів, що вимагають 5-кратного обчислення функції правої частини на кожному кроці інтегрування (і-етапні методи). Формули цих методів добре пристосовані для практичних розрахунків: вони дають змогу легко змінювати крок інтегрування, є однокроковими, достатньо економічні (принаймні, до формул четвертого порядку включно). Явний метод Ейлера можна розглядати як одноетапний метод Рунге-Кутга.
480 8.3. Методи Рунге-Кутта Найвідомішою є формула чотириетапного явного методу четвертого порядку точності. Її називають РК4: Хп+1 =Хп+ 7^1 + 1к2 + 2к3 +к4Ї’ 6 *і =*■/(*,,»*,,)» к2 =к-№„+\,хп+\к1), ( (8 3 2) кз =Ь-№п+±,хя+.\к2), к4 = Ь’/Ця+11,хп+к3). 8.3.1. Оцінка похибки на основі формул різної точності Цей спосіб базується на використанні двох наближених значень розв’язку в одній точці [5]. Проте ці наближення, на відміну від правила Рунге, обчислюють не за однією, а за двома формулами різних порядків точності р і 5 з однаковим кроком. Розглянемо загальний випадок, коли застосування формули Рунге- Кутта не взаємозв’язане одне з одним, а потім перейдемо до розгляду спеціально підібраних формул. 8.3.2. Комбінація незалежних формул *і=*о+Е^Л(А)> <8-3-3) /=і £і(/г) = /г/(4„х0), к2(И) = А/ (г0 + а26, х0 + р 2Д£і (А)), к3 (А) = /г/(^0 +адИ,х0 +р?1£1 (А) + ... + Рад_1^_і (Л)) > де а, , рі ; , рді числа [5], які обираються так, щоб вираз (8.3.3) збігався з розкладом у ряд Тейлора до максимально можливої степені задовільних правих частин / (хл) та довільного кроку А . Такий спосіб засновано на комбінації двох формул виду (8.3.3) різних порядків точності р і 5:
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 481 хі = хо + Z/Vа > /=1 ki=hf(t0,x0), (8.3.4) k,=hf /-1 t0 +aih,x0 +Yß>i,jkj та xl=x0 +^Prßi , /=1 k = л/('о,*о)> к,=¥ (8.3.5) і-і 'о +аЛ*о +ЕР/,Л У=і Нехай р > 5 , /* > Я . Тоді локальні похибки набувають вигляду: р<’=*(;(,+й)-< = о(л'»'), р'=і((,+Л)-х?=0(А"1). Звідси випливає оцінка локальної похибки формули (8.3.5) р* = х? - < + о(лр+1) . (8.3.6) Знехтуємо членами вищого порядку малості, отримаємо р’^хї-хї. (8.3.7) Отримана оцінка вимагає г + г -1 обчислень правої частини. 8.3.3. Комбінація спеціальних формул Якщо коефіцієнти у формулах (8.3.4) і (8.3.5) такі, що а, = а, , ß, у = ß, y , і = 1,2,...,? , (8.3.8) то £, =£, , / = 1,2,...,г , і для локальної похибки (8.3.7) формули (8.3.5) отримаємо такий вираз [5]: Ps =xf-xt = . (8.3.9) 7=1 16 7-451
482 8.3. Методи Рунге-Кутта Де Чі - Рі ~Рі , = 1,2,...,г , (8.3.10) Чі=Рі , ї = г + 1,2,...,г. Оцінка (8.3.9), окрім тих значень правої частини, які обчислюють на поточному кроці к і входять до (8.3.5), містить додаткові значення кі , і = г + 1,...,г . Це дає змогу зменшити кількість обчислень правої частини порівняно з правилом Рунге та оцінкою (8.3.9). Оцінка (8.3.9), а також точніша оцінка (8.3.7), є асимптотичними, оскільки вони враховують лише члени головного порядку, і справедливі за достатньо малих величин кроку інтегрування. ♦ На практиці наближеним значенням розв’язку вважають х[ як таке, що має дещо вищий порядок точності. Г Величина E = ^qiki , де коефіцієнти визначають з /=і допомогою (8.3.10), називають контрольним членом [5]. У випадку системи диференціальних рівнянь контрольний член можна записати у формі: £=Е?Л/,;'=і,2,...,м. («злі) /=і 8.3.4. Контрольні члени методів Рунге- Кутта Якщо у виразі (8.3.3) прийняти а2 = , а3 = 1, одержимо метод із сім’ї Рунге-Кутта [5]: *і = х0 +—(&і +4£2 + *з)> (8.3.12) 6 =л/0ь»*ь); і і Л к3=¥(і0 +М0 -*1+2*2), 1 а при а2 = — - метод:
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 483 Ху^Хц+к^, (8.3.13) k1=hf(t0,x0); 1 1 ^ k2=W[to + 2h>xo + 2kl Обидва методи (8.3.12) та (8.3.13) задовольняють умову (8.3.8). Контрольний член Е = -(к1-2к2+к3) має порядок о(И3) . 6 Тут р = 3 , 5 = 2, г = 3 , ґ = 2 . Якщо оцінку для локальної похибки методу (8.3.13) здійснити за правилом Рунге, то це потребуватиме п’ять обчислень правої частини замість трьох. 8.3.5. Модифікація Мерсона Xi=x0+Ukl+4ki+k5); О ki=hf(t0,xQ); 1 1 4 k2=hf /0+-/г,х0+-£і *з=¥ (8.3.14) К =А/^о +\к’хо + \к\ ( 1 3 л кь=¥ іо+Кх0+-кх--кі+2кі V ^ ^ > Формули (8.3.14) і формула третього порядку точності: хх =х0 +^(^і +3*3 +4к4+2к5) (8.3.15) задовольняють умову (8.3.8). Контрольний член: £ = ^(2*,-9*з+8*4-*5) має порядок о(А4) . Тут р = 4, 5 = 3, г = 5 , г = 5 . Якщо оцінку для похибки методу третього порядку виконувати за правилом Рунге, то це потребуватиме вісім обчислень правої частини замість п’яти за методом Мерсона. На більш вузькому класі лінійних рівнянь виду:
484 8.3. Метода Рунге-Кутта х'= / (х,() = аґ + Ьх + с (8.3.16) формула (8.3.15) має не третій, а п’ятий порядок точності. Порядок точності формули (8.3.14) залишається четвертим. Тому величина контрольного члена слугує головним членом локальної похибки формули (8.3.14) і має порядок о(к5). Отже, метод Мерсона має ту особливість, що на класі рівнянь (8.3.16) головний член локальної похибки виражається з допомогою лінійної комбінації лише тих значень правої частини, які безпосередньо входять у формулу (8.3.14). Відповідно, для отримання оцінки похибки зникає необхідність у додаткових обчисленнях. 8.3.6. Модифікація Фельберга Фельберг розробив множину методів, що задовольняють умову (8.3.8). Наведемо формули четвертого і п’ятого порядків: *1(4) = *0 + 25 , 1408, 2197, 1, к, + к, + к. —к5; 216 1 2565 3 4104 4 5 5 х<5) =х0 +—*і +-^Ц +^^кА ~—к5 +—к6; (8.3.17) 1 0 135 1 12825 3 56430 4 50 5 55 6 К =hf{(o>xo); і і N к2=hf t0+-h,x0+-kl 4, 4 _ 3 3 9 k3=hf\t0+-h,xо + —+—k2 , ..( 12, 1932, 7200, 7296, *4 =hf \ tn +—h,xa + к, £, + к, і, 4 'V 13 0 2197 2197 2 2197 3J , і. 439» о/ 368°, 845 / 4 k* = hf\ xn + A,xft + кл -8 к7 + к a 5 J ^ 0 0 216 1 2 513 3 4104 4 , ,J 1, 8 , 3544, 1859, 11.' b = hf\ tn + —h, xn л, + 2Ar, к, + к» к, 6 jyo 2 ’ 0 27 1 2 2565 4104 4 40 5 Контрольний член: 1 /, 128 _ 127 .1 .2
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 485 має порядок о(И5) [5]. Тут р = 5 , 5 = 4, г = 6 , г = 5 . Якщо оцінку для похибки методу четвертого порядку виконувати за правилом Рунге, то це потребуватиме одинадцять обчислень правої частини замість шести за методом Фельберга. Завдання для самостійної роботи Запрограмувати та дослідити на тестових прикладах методи Мерсона та Фельберга. 8.4. Жорсткі системи диференціальних рівнянь У випадку систем лінійних диференціальних рівнянь поряд- dx ку N: — = Ax(t) , де А - квадратна матриця розміру (N х N), існує dt N чисел, що обмежують величину кроку h. Цими числами є корені характеристичного рівняння det(А-ЯtE) = 0, де Е - одинична матриця; Я t - власні значення матриці А. Для систем нелінійних диференціальних рівнянь порядку N: ^ = /(*(0,0 (8.4.1) at r{f роль матриці А відіграє матриця Якобі системи Ja - —-. ckj Властивості системи диференціальних рівнянь залежать від того, на скільки власні значення її матриці відрізняються одне від одного. Якщо вони різняться між собою на декілька порядків, то математичну модель системи називають жорсткою (stiff) [82, 89]. Увага! Жорсткість - це властивість математичної моделі системи, а не самої системи. Із курсу математики відомо, що набір власних чисел матриці з дійсними коефіцієнтами (її спектр) може містити як дійсні, так і комплексно-спряжені значення. З погляду оцінки властивостей математичної моделі, можна виокремити три характерні випадки розташування власних значень (рис. 8.2).
486 8.4. Жорсткі системи диференціальних рівнянь Іт(к) Ха(Х) ІяШ і Ь і і д 4 і. *•(*) *) б> •) У Рис. 8.2. Характерні випадки розташування спектра матриці Випадок, проілюстрований на рис. 8.2, а, з погляду математичного моделювання найпростіший, оскільки розкид власних значень є незначним. Випадок, проілюстрований на рис. 8.2, б, характеризує жорстку математичну модель із так званим пограничним шаром. Найбільше за модулем власне значення обмежує максимально допустиму величину кроку інтегрування явним методом Ейлера. Найменше за модулем власне значення визначає тривалість перехідного процесу у системі. Великий розкид дійсних власних значень спричинює до необхідності інтегрування системи (8.4.1) з надто малим кроком й упродовж значного проміжку часу [ґ0, ік]. Випадок, проілюстрований на рис. 8.2, в, є найнеприємнішим для моделювання. Комплексно-спряжені власні значення з великими уявними частинами спричиняють до виникнення швидко- осцилюючих функцій-розв’язків системи (8.4.1). Це випадок жорсткої моделі з осцилюванням. Перехідний процес у таких системах іноді триває впродовж десятків, а то й сотень квазіперіодів коливань осцилюючої функції. Інтегрування кожного з цих квазіперіодів вимагає декількох сотень кроків А, що, відповідно, спричинює до величезних затрат процесорного часу. Моделювання встановлених періодичних режимів подібних систем, які називають слабодемпфованими, вимагає застосування спеціальних алгоритмів прискореного пошуку періодичних режимів. У радіоелектроніці ці системи називають високодобротними. Жорстку задачу інколи називають “задачею із великою константою Ліпшиця”. Якщо похідні д/1 дх неперервні та обмежені, константа Ліпшиця визначається як Ь = ||д// 5х|| > р(д/ / дх),
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 487 де р= шах ЇХ, І - спектральний радіус матриці. Розв’язувати жорсткі математичні моделі явними методами складно, а іноді й неможливо. Для подібних задач розроблено іншу сім’ю чисельних методів - неявні методи інтегрування. Здебільшого, тут застосовують методику’ прогнозу-корекції. Вона полягає в тому, що дискретне значення вектора розв’язку в т + 1-й точці спочатку прогнозують, наприклад, за лінійною формулою. Унаслідок цього одержують систему нелінійних алгебричних рівнянь. Процедура корекції - це розв’язання цієї системи відомим нам методом 'Ньютона для уточнення значень вектора розв’язку із заданою точністю є. застосовують для розв’язання систем рівнянь, що володіють властивістю “жорсткості”, тобто при моделюванні процесів, мате- Неявність методу полягає в обчисленні дискретних значень вектора розв’язку х в (т +1) -й точці на основі вектора похідної /(хт+1,ґт+1) в шуканій точці. Оскільки його значення у справжній точці хт+1 є невідомими, то розпочинаємо обчислення з лінійного прогнозу значень вектора хт+1, обчислення, за цим прогнозом, вектора / з подальшою корекцією значень хт+1 ітераційним методом Ньютона. Введемо нові позначення, зміст яких бачимо нарис. 8.3: Хт_х = ХМ - вектор змінних у попередній точці; Хт -X- вектор змінних у поточній точці; 8.5. Неявний метод Ейлера Неявні методи інтегрування систем ЗДР: -Г = Д*>0, *(0) = х0 ш (8.5.1) з великим (8.5.2)
488 8.5. Неявний метод Ейлера Х„+1 = ХР - прогнозоване значення вектора Хт+1 у точці tm+l. Чисельний метод (8.5.2) дискретизує задачу (8.5.1), що зводить її до системи нелінійних алгебричних рівнянь: FI(XP) = XP-X-hf(XP,tp) = 0. (8.5.3) Перехід від прогнозованого значення ХР до “точного” значення Хт+1 на кожному кроці інтегрування здійснюється шляхом розв’язання системи (8.5.3) ітераційним методом Ньютона: хр(к+ц = хр(*) _ DXW, (8.5.4) де к- номер ітерації Ньютона. А* »ИТ Хт Хт+1 ИМ h tm-l tm tm+1 Рис. 8.3. До алгоритму НМЕ Початкові умови ХРт для цього ітераційного процесу отримуємо за формулою лінійного прогнозу: ХР = -(Х- ХМ) + X. (8.5.5) ИМ Вектор нев’язки ИХ^ для ітерацій (8.5.4) знаходимо із системи лінійних алгебричних рівнянь: Іас(ХР{к)^р{к)) ■ ИХ(к) =' = РІ(ХРік\ір(к)). (8.5.6) Вираз для матриці Якобі Jac(XP{k), tPik)) = dFI^^tP\ яка належить до системи (8.5.6), знайдемо, диференціюючи функцію FI(XP) по ХР: dFI(XP,tP)_(E h df(XP,tP)h де дХР df(XP,tP) дХР дХР - матриця Якобі правої частини системи (8.5.1).
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 489 8.5.1. Алгоритм вибору початкового кроку інтегрування Розрізняють крок інтегрування і крок виведення результатів інтегрування на графік. Крок інтегрування И, здебільшого, є величиною змінною. Для жорстких систем диференційних рівнянь він є величиною значно меншою від проміжку інтегрування |/0,^], отож, кількість кроків може дорівнювати декільком тисячам. На графічний екран у режимі VGA ми можемо вивести щонайбільше 640 точок. У масив чи файл доцільно записувати значення змінних не в усіх точках інтегрування, а лише у певних проміжних точках, відстань між якими є однаковою. Ми її позначаємо Н0 і називаємо базовим кроком виведення результатів. Величину Н0 обчислюємо за формулою HO = (t0 - tk)/Ngr, де Ngr - задана нами кількість точок графіка (Ngr <640). Початковий крок інтегрування h, як і поточний крок, не може перевищувати значення HO. Обираємо цей початковий крок кратним HO, обчислюючи його величину шляхом поділу HO на 2 необхідну кількість разів. Цю кількість визначаємо з умови Dmax<Fimax-h, де Fimax - максимальне значення компоненти вектора F - правої частини системи (8.5.1), обчисленого для початкових умов (рис. 8.8). Про Dmax - див. нижче. 8.5.2. Алгоритм вибору поточного кроку інтегрування У процесі інтегрування системи (8.5.1) крок h може збільшуватись, зменшуватись, а також певний час залишатись незмінним. Його величина адаптується до локальної поведінки математичної моделі досліджуваної системи. Зміни кроку у нашому алгоритмі виконуються на основі такого емпіричного правила [69]: Вводимо дві пари констант, значення яких обираємо на підставі певних фізичних міркувань: • Ктах, Kmin - цілочисельні константи, які обмежують, відповідно, максимально і мінімально допустиму кількість ітерацій за Ньютоном. Якщо в процесі ітераційного уточнення прогнозованих значень вектора невідомих у
490 8.5. Неявний метод Ейлера момент часу ti+l число ітерацій перевищить значення Ктах, - прогноз відкидається, крок h ділиться навпіл і програма починає новий прогноз зі зменшеним значенням h\ • Dmax, Dmin - константи дійсного типу, які обмежують, відповідно, максимально і мінімально допустиму величину приросту змінних на кроці h. Якіцо під час ітерацій Ньютона приріст значення хоча б однієї змінної Хі перевищить Dmax, прогноз також відкидається. Крок h ділиться навпіл і програма починає робити новий прогноз зі зменшеним значенням h. Іншими словами, крок h ділимо навпіл, якщо хоча б одна із двох перелічених вище умов виконається. Спробу збільшення значення h вдвоє алгоритм робить після кожного вдалого уточнення прогнозу вектора невідомих. Це відбувається за одночасного виконання двох умов: • прогноз вдалось уточнити за кількість ітерацій, яка не перевищує значення Kmin; • максимальний приріст кожної змінної при цьому не перевищив значення Dmin. Значення названих чотирьох констант доцільно обирати такими: Ктах = 9.. 15, Kmin = Ктах Div 3. Dmax має бути таким, щоб кількість кроків на періоді була не меншою за 100. Dmin = Dmax/3.
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 491 8.5.3. Позначення блок-схем НМЕ Алгоритм НМЕ складається* із декількох блок-схем, які наведено на рис. 8.7, рис. 8.8, рис. 8.9 та рис. 8.10. Пояснимо призначення ідентифікаторів, які використано у цих алгоритмах: • N - розмір системи диференціальних рівнянь (8.5.1). • Ngr - кількість точок графіка функції-результату. • є - точність, після досягнення якої ітерації Ньютона припиняються. • tk- кінець проміжку інтегрування. • Ктах, Kmin - цілочисельні константи, які обмежують, відповідно, максимально і мінімально допустиму кількість ітерацій за Ньютоном. Використовуються в алгоритмі автоматичного вибору кроку h. • Dmax, Dmin - константи дійсного типу, які обмежують, відповідно, максимально і мінімально допустиму величину приросту змінних на кроці h. Використовуються в алгоритмі автоматичного вибору кроку інтегрування h. • h - поточний крок інтегрування. • ИМ- попередній крок інтегрування. • ХМ - значення вектора розв’язку у момент часу tm_x. • X- значення вектора розв’язку у момент часу tm . • ХР - значення вектора розв’язку у момент часу tm+l. Спочатку це прогнозоване, а потім - уточнене ітераціями Ньютона значення.
492 8.5. Неявний метод Ейлера • Кі, N11 - лічильники загальної кількості ітерацій та кроків інтегрування, відповідно. • Tg - масив розмірності [0..640\ дійсних значень рівномірних відліків аргументу розв’язку системи (8.5.1) для виведення функцій розв’язку на графік. • Mg - масив розмірності [/..ІУ, 0..640] дійсних значень функцій розв’язку системи (8.5.1) для виведення їх на графік. • НО -“базовий” крок переміщення по осі аргументу для періодичного запису в масив Mg значень компонентів вектора А". • /а - матриця Якобі системи (8.5.3) розміру (Л^*Л0- • F - вектор для зберігання поточних значень функцій правої частини системи (8.5.1). • П - вектор для зберігання поточних значень функцій системи (-8.5.3). • ОХ - вектор для зберігання поточних значень нев’язки для методу Ньютона. • ДХ/и - поточне значення максимальної компоненти вектора ОХ. • Я- робоча змінна дійсного типу. Ж • / - поточний час інтегрування: * = + • «=1 • Л - індекс для запису значень аргументу і функцій в масиви Tg і Mg.
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 493 8.5.4. Блок-схеми алгоритмів \ Рис. 8.4. Алгоритм головної програми для методів моделювання
494 8.5. Неявний метод Ейлера Г 2 1 FM ( NMF) г-И—*— і і =1 ХгХ(НК1(*2*К2(*2* КЗ(*К4,)/6 і + І Рис. 8.5. Алгоритм Рис. 8.6. Алгоритм методу Рунге-Кутта четвертого порядку явного методу точності (РК4) Ейлера (ЯМЕ)
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 495 Рис. 8.7. Алгоритм неявного методу Ейлера (НМЕ)
496 8.5. Неявний метод Ейлера Рис. 8.8. Алгоритм вибору початкового кроку: Krok Рис. 8.9. Алгоритм Ньютона: Newtlter
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 497 Рис. 8.10. Алгоритм обчислення Рис. 8.11. Алгоритм обчислення матриці матриці Якобі д ^ • Jacob Якобі : Jac дХР дХР
498 8.5. Неявний метод Ей лера of Extended; of Extended; of Extended; of Extended; 8.5.5. Програма для розв'язання систем ЗДР Program XIO_MODELLING; {$N+> { Директива вмикання математичного копроцесора для обчислень в Extended } Uses Crt, Graph; Type Vector = Array [0..640] Vec = Array [0..40] Matr = Array [1..5, 0..640] Matrix = Array [ 1. . 5, 1..5 ] Var JA : Matrix; MXg : Matr; Tg : Vector; F, X, Xm, Fi, Dx : Vec; MaxX, MaxY, MinX, MinY, Kx, Ky, Zx, Zy, Gx, Gy, Krx, Kry: Extended; xx, yy, ay,bx,t, tO, tK, h, H0,hM, Eps, Dmax, Dmin, Q:Extended; N, NGR, KL, KrokX, KrokY, Kmax ,Kmin zLonglnt; L, MET, LL, Ki, NK : Longlnt; Drv, Dm, i, jj : Integer; Lf :Stringr[48] ; k2 :Strlng[23]; Xt, Yt, Lt '.String; Procedure FM(N:Integer; X:Vec; t:Extended; Var F:Vec); Var R : Extended; Begin F [ 1] : = X [ 2 ] ; F[2] := -15*F[1] - 200*X[1] - 200*X[1]*X[1]*X[1]; End; '■ \ {$i Gauss.pas} Procedure Krok (X: \ Vec; Var h: Extended; Var XM: Vec) ; Var і : R : Begin Eps : Integer; Extended; = 0.0001; Q := 0.001 * Eps; Kmax := 9; Kmin Dmax := 0.1; Dmin Ki := 0; Nk := 0; h := HO; EM (N, X, t, F); R := F[1]; For і := 2 to N do If Abs (F[i]) > R then R := Abs (F[i]); While R * h > Dmax do h := h / 2; = Kmax Div 3; = Dmax / 3;
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 499 hM := h; For i := 1 to N do XM[i] := X[i] - h * F[i] ; t := h End; Procedure Jac ( X: Vec; t: Extended; Var JA: Matrix) ; Var FP : Vec; i, j : Integer; Begin EM (N, X, t, F); For j := 1 to N do Begin X[j] := X[j] + Q; EM (N, X, t, FP); For i := 1 to N do JA[i, j] := (FP[i] - F[i]) / Q; X[j] := X[j] - Q End End; Procedure Jacob (XP: Vec; t: Extended; Var JA: Matrix) ; Var i, j : Integer; Dx : Vec; Begin JAC (XP, t, JA) ; For i := 1 to N do Begin For j := 1 to N do JA[i, j] := - h * JA[i, j]; JA[i, i] := 1 + JA[i, i] End End; Procedure J__E (N: Integer; Var h, t: Extended; F: Vec; Var X: Vec) ; Var i : Integer; Begin EM (N, X, t, F); For i := 1 to N do X[i] := X[i] + h * F[i] End; Procedure RK4 (N: Integer; Var h, t: Extended; F: Vec ; Var X : Vec) ; Var i : Integer; Kl, K2, K3, K4, Y : Vec; Begin EM (N, X, t, F); For i := 1 to N do Begin Kl[i] := h * F[i] ; Y [i] i= X [i] + Kl [i] / 2
500 8.5. Неявний метод Ейлера End; FM (N, Y, t + h / 2, F) ; For i := 1 to N do Begin K2[i] := h * F[i]; Y[i] := X[i] + K2[i] / 2 ) End; ( EM (N, Y, t + h / 2, F) ; For i := 1 to N do Begin K3[i] := h * F[i]; Y[i] :*= X [i] + K3[i] End; FM (N, Y, t + h, F) / For i := 1 to U do K4[i] := h * F[i]/ For i := 1 to N do X[i] := X[i] + (K1[i] + 2 * K2[i] + 2 * K3[i] + K4[i])/6 End; Procedure Newt_Iter (t: Extended; Var Dxm: Extended; Var XP:Vec) ; Var i : Integer; FI : Vec/ Begin EM (N, Xp, t, F); Jacob (XP, t, JA) ; For i := 1 to N do FI[i] := XP[i] - X[i] - h *F[i]; Gauss (JA, FIN, Dx) ; Dxm := 0; \ For i := 1 to N do \ Begin XP[i] := XP[i]-Dx[i]; If Dxm < Abs (Dx[i]) then Dxm := Abs (Dx[i]) End End; Procedure NJ_E (N: Integer; Var h, t:Extended; F:Vec ; Var X : Vec) ; Label 1, 2; Var R, Dxm : Extended; XP : Vec; i, j, k, ii : Integer; Begin 1: For i := 1 to H do XP[i] := h * (X[i] - XM[i]) / hM + X[i]; For k := 1 to Kmax do Begin
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 501 Newt_Iter (t, Dxm, ХР); Кі := Кі + 1; If Dxm >= Eps then Begin If Dxm > Dmax then Begin h := h / 2; t := t - h; Goto 1 End End Else Goto 2 End/ Begin h := 0.5 *h/ t := t - h; GOTO 1 End; 2: Nk := Nk + 1/ For і := 1 to N do Begin ХМ[і] := X [i]7 X[i] := XP[i] End; hM := h; If ( k <= Kmin ) And ( Dxm <= Dmin ) then h :: If h > HO then h := HO 7 End; BEGIN { Початок головної програми } Writeln (' Введіть через інтервал:') 7 Writeln ('N - розмір математичної моделі/'] Writeln ('t07 tk - інтервал інтегрування/' ] Writeln ('Ngr - кількість точок графіка (<= Readln (N, tO, tK, Ngr)7 HO := (tK - tO) / Ngr7 Tg[0] := tO 7 Tg[1] := HO7 jj := i; Writeln (' Введіть вектор початкових умов X For і:=1 to N do Begin Write (’ХГД, ’] = ')/ Read (X[i] ) 7 MXG[і,0] := X[і] End; Repeat Writeln ('Введіть правильно номер методу інтегрування:'); Writeln (11 - Явний метод Ейлера') ; h + h; г 640)')7
502 8.5. Неявний метод Ейлера Writeln (' 2 - Метод РК4'); Writeln ('З - Неявний метод Ейлера'); Readln (MET); Until (MET = 1) or (MET = 2) or (MET = 3); Case MET of x 1,2 : Begin [ Writeln ('Введіть крок інтегрування h <=',HO:15:5); Readln (h) End; 3 : Krok (X, h, XM) ; End; Repeat Case MET of 1: J_E (N, h, t, F, X) ; 2: RK4 (N, h, t, F, X); 3: NJJE (N, h, t, F, X) End; t := t + h; If t > Tg[jj] then Begin For і := 1 to N do MXG[i,jj] := X[і]; Tg[jj + 1] := Tg[jj] + HO; jj := jj + 1 End; Until t >= tK; If MET = 3 then Begin Writeln ('Кількість кроків Nk=',Nk/' Кількість ітерацій Ki=' , Кі) ; Readln End; Drv := Detect; InitGraph {Drv, Drm, f C: \BP\B6I') ; Repeat OutTextXY (100, 100, 'Введіть LL -> N змінної для графіка,'); OutTextXY (100,120,'або Q чи q -> для виходу'); Readln (Lt); ClearDevice; If (Lt = 'Q') or (Lt ='q') then Exit else Val (Lt , LL , i); MinX := TG[0]; MaxX := TG[NGR-1]; MaxY := MXG[LL,0]; MinY := MXG[LL,0]; For і := 0 to NGR - 1 do Begin If MaxY < MXG[LL, i] then MaxY := MXG[LL, i]; If MinY > MXG[LL, i] then MinY := MXG[LL, i]
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 503 End; L := 80; SetBkColor ( White) ; SetlineStyle (0, 0, 3); Kx := (GetMaxX - 2 * L) / (MaxX - MinX); Ky := (GetMaxY - 2 * L) / (MinY - MaxY); Zx := (GetMaxX * MinX - L* (MinX + MaxX)) / (MinX - MaxX); Zy := (GetMaxY * MaxY - L* (MinY + MaxY)) / (MaxY - MinY) ; If Minx * Maxx <= 0 then Gx := 0; If Minx * Maxx > 0 then Gx := Minx; If ( Minx * Maxx>0 ) and ( Minx < 0) then Gx := Maxx; If ( Miny * Maxy<= 0) then Gy:=0; If ( Miny * Maxy> 0 ) and ( minY > 0) then Gy := Miny; If ( Miny * Maxy> 0 ) and ( MinY < 0) then Gy := Маху; ay:=Kx * Gx+Zx; bx:=Ky * Gy + Zy; SetColor (Blue); SetLineStyle (0, 2, 3) ; Line (L, Round (bx) , Round (GetMaxX - L) , Round (bx) ) ; Line (Round (ay), 1, Round (ay), Round (GetMaxY - L)); SetLineStyle (3, 0, 1) ; KrokX:= {GetMaxX - 2 * L) Div 10; KrokY:= (GetMaxY - 2 * L) Div 10; For i:=l to 9 do Begin Line (L, L + і * Kroky, GetMaxX - L, L + і * Kroky); Line (L + і * Krokx, L, L + і * Krokx, GetMaxY - L); Krx := (Maxx - Minx)/10.0; Kry := (Маху - Miny)/10.0 End; xx := Minx; уу := Маху; For і := 0 to 10 do Begin Str (xx:7 :3,... xt) ; OuttextXY (L-30 + i*Krokx,-20 + GetMaxY - L div 2, xt) ; Str (yy:7:3, yt); OuttextXY (L - 65, L + і * Kroky, yt); xx := xx + KrX; yy := yy - KrY End; MoveTo (Round(Kx*Tg[0] +Zx) , Round(Ky*MXg[LL, 0]+Zy)); SetColor (Red); SetLineStyle (0, 0, 3); For i:=0 to Ngr - 1 do LineTo (Round (Kx*Tg[i]+Zx) , Round (Ky*MXg[LL,i]+Zy)); ReadLn; ClearDevice; Until (LL > N) END.
504 8.6. Тестові задачі 8.6. Тестові задачі Задача 1. Моделювання візочка масою т, жорстко приєднаного до стіни трьома пристроями для гасіння удару (демпферами) [112]. Це - лінійна пружина з коефіцієнтом жорсткості к, нелінійна “кубічна” пружина, яка створює гальмівну силу, пропорційну кубові відхилення з постійним коефіцієнтом к*, і спеціальний демпфер, гальмівна сила якого пропорційна швидкості візка з коефіцієнтом пропорційності с (рис. 8.12). ► де Рис. 8.12. Візок з потрійним демпфуванням Якщо початок системи координат розмістити так, як на рис. 8.12, то загасаючі коливання візка описуються нелінійним диференціальним рівнянням другого порядку: 2 * 4 х <ІХ . ,* з . т—т- + с— + кх + к х =0. Л2 А Змоделюємо динаміку цієї системи на проміжку часу |70,^], тривалістю 1с. Виберемо такі фізичні параметри системи: к = 2.0—; £*=2.0-^т-; с = 0.15^ °; т = 1.0 кг. см см см Перетворимо диференціальне рівняння другого порядку в систему двох диференціальних рівнянь першого порядку: сіх & <Ь& - = *і Л І-Г • — х2 ,
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 505 сіх, - = х- 29 ь л і — = *2 Х\~- ж сіх2 Ж т т т Підставляючи у цю систему числові значення параметрів у такій системі одиниць, щоб зміщення х виражалось у сантиметрах, одержимо готову для моделювання систему в нормальній формі Коші: Жеі - = х0 2 _ Ж = -15.0*2 ” 200*! - 200*1 Обираючи початкові умови: х(0) = 10ам; с!х( 0) Ж = 0, одержимо графіки загасання коливань візка такі, як на рис. 8.13 та рис. 8.14. У разі використання програми хіо__мооеііЬШЄ для моделювання задачі 7, діалог з програмою для введення вхідних даних буде такий: Введіть через інтервал: N - розмір математичної моделі; 1:0; tk - інтервал інтегрування; Ыдг - кількість точок графіка (<= 640) 2 0 1 400 «— Вводимо. Введіть вектор початкових умов X X [ 1 ] = 10 <— Вводимо. X [ 2 ] = 0 <— Вводимо. Введіть правильно номер методу інтегрування: 1 - Явний метод Ейлера 2 - Метод РК4 3 - Неявний метод Ейлера З <— Вводимо. Із завершенням процесу моделювання отримаємо повідомлення та один із двох графіків (рис. 8.13 або рис. 8.14): Кількість кроків Ык= 1741 Кількість ітерацій Кі=4923 л
506 8.6. Тестові задачі 0.000 0.100 0.200 0.299 0.399 0.499 0.999 0.690 0.798 0.898 0.997 Рис. 8.13. Графік зміщення візка від положення рівноваги в часі (х{) Рис. 8.14. Графік зміни швидкості візка в часі ( х2) Задача 2. Моделювання вимушених коливань у послідовному RLC -контурі. L Рис. 8.15. Послідовний коливний контур
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 507 Такий контур можна описати диференціальним рівнянням: ^~сІЇ + (5 ^ + ^ = ’ де е0 - амплітуда вхідного синусоїдного сигналу, а у - його лінійна частота. Це рівняння можна звести до системи двох диференціальних рівнянь першого порядку: Ь— + Ш + ис = е08іп(2 пуі) Ж а =і А Я . 1 тт о- ч — = —і ис + е08іп(2ягО А Ь Ь аис і. —-=—і Остаточний вираз І А С Залежно від параметрів контуру, встановлення динамічного режиму може тривати від декількох періодів вхідного сигналу до декількох десятків періодів. Введемо позначення: лс, = і, а х2 математичної моделі схеми, що на рис. 8.15: сіх, Л 1 —= —X, х2+ е08іп(2яг/) А Ь Ь Ас-, 1 —- = —X, . А С 1 Обчислимо добротність і2 контуру для зазначених номіналів. -е*32- Рис. 8.16. Графік перехідного процесу в контурі (рис. 8.15)
508 8.6. Тестові задачі Задача 3. Моделювання однопівперіодного випрямляча (рис. 8.17). Оберемо напрями напруг і струмів кожної гілки схеми так, як це проілюстровано на рисунку. Оскільки схема налічує 4 ємності і 1 індуктивність, її математичною моделлю слугуватиме система п’ятьох ЗДР з п’ятьма невідомими, які ми позначили, ВІДПОВІДНО, *1, *2, *3, *4, іг>=1Е-6(Ехр(10хг1)) . о, Кі ш £•1 0.1 ' ісз 'І \ *П2 иа 1Е-3 Т ■ 1000 ЛиЯ2 Е,=10*Ьіп(120*Р±*і) Рис. 8.17. Однопівперіодний випрямляч Побудуємо математичну модель схеми, використовуючи закони Кірхгофа й Ома.
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 509 гіис2 _ 1 , ,, тт р ч 1 . ^-Е£г СІ С11С~г1 ’ иь + исг = иС2; иь = Ь^- = иС2 - исз; ^-—(ис2-исз). л С 2 СЗ/.., л^с1= _1_ 3 А Ь Д2 сз ^сз 1. 1 — і і Ж С3 11 Д2С3 сз Одержані рівняння запишемо як систему у нормальній формі Коші, що й слугуватиме математичною моделлю нашого випрямляча. ^- = 0.2 * 10б (-лі - х2 +10 * 8іп(120 * я- * 0)-ів & ^- = 0.2*103(-лі-Хг+10*8іп(120*я-*О-^з) & дхг ~йі — = 10(х2 - х4) ^- = 103Лз-х4 І ш ів =10"6(еІОдг' -1). Г
510 8.6. Тестові задачі 8.7. Багатокрокові методи Серед багатокрокових методів значне розповсюдження отримали лінійні багатокрокові методи. В моделюванні найчастіше використовують лінійні багатокрокові методи двох видів: типу Адамса та жорсткостійкі методи Гіра [89]. Подаємо вираз, який об’єднує обидва ці типи: к к хт+1 = Z« іХт-і ifm-i • (8.10.1) /=0 ‘ і=-5 При а(=0 для всіх />1 отримуємо методи Адамса, а при Р і= 0 для всіх і < 1 — методи Гіра. Якщо S = 0, то вираз (8.10.1) буде явним, 5 = 1- неявним. Особливий клас лінійних багатокрокових методів отримують при S > 1. їх називають розтягнутими (extended) або “із забіганням вперед”. Явні методи Адамса називають методами Адамса- Башворта, а неявні - Адамса-Маултона. Метод Адамса-Башворта 1-го порядку - це відомий нам явний метод Бйлера: хт+1 = хт + hf(xm,tm). (8.10.2) Відомо, що А-стійких методів Адамса-Башворта не існує, а серед методів Адамса-Маултона такою властивістю володіють лише неявний метод Ейлера: хт+1 = хт hf C*m+1 »^/n+1) (ß'^0*3)
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 511 і метод трапецій: Хт+\ ~ Хт + Л/2 (Дхт+1 >(т+1 ) + /(**>'*»• (8-10.4) Отож, для інтегрування жорстких систем методи Адамса підходять мало. Методи Гіра [114], в основу яких покладено формули деференціювання назад (ФДН), дають змогу виразити похідну х' через значення вектора змінних на попередньому кроці: /=0 Оскільки вони є жорсткостійкі, то це дає змогу застосовувати їх для систем, які використовують математичні моделі, виражені у сіх неявній формі F(x,—,0 = 0. Ж 8 • 7 .1. Метод Шичмена У 1970 році опубліковано один із найпопулярніших методів із сім’ї Гіра - метод Шичмена [115]. Це неявний метод другого порядку точності. Практика використання методів Гіра в алгоритмах із автоматичним вибором порядку методу засвідчує, що переважна більшість жорстких ММ інтегрується власне цим методом. За використання постійного кроку інтегрування к метод Шичмена задається таким виразом: 1 4 2 *т+1 = ~з*т-1 + з ** +^¥(хт+і,Іт+і) ■ (8.10.6) Якщо ввести позначення: ^ 1= ^т+\ ~ Іт І Ь 2~^т ~ ^т-ї ? одержимо чисельний метод Шичмена для інтегрування зі змінним кроком к : *і = ^ х + (/гі+/г2>2 /(х ^ ) .(8.10.7) т+1 /ї2(2/г, +/г2) т"‘ /г2 (2/гг +/г2) т 2/г, +й2 т1 1 У [115] наведено формулу для обчислення локальної похибки, яку одержують за використання методу (8.10.7): т+1 6(2/?!+^) де Г*є[ґш,?т+1].
512 8.7. Багатокрокові методи Вираз (8.10.8) використовують в алгоритмах автоматичного вибору кроку h. Завдання для самостійної роботи Запрограмувати метод Шичмена (8.10.6). Дослідити на тестових задачах його ефективність і точність. 8.8. Алгоритми автоматичного вибору величини кроку h Для високоточних програм чисельного інтегрування необхідно завжди дотримуватися вимог точності до обчислень. Отож, практично в усіх подібних програмах встановлюють максимально допустиму локальну похибку обчислень або діапазон зміни похибки на всьому інтервалі інтегрування. Оскільки надто жорсткі вимоги до точності суттєво збільшують затрати машинного часу, то виникає необхідність визначення максимально можливої величини кроку. Отже, необхідно здійснювати інтегрування з максимально великим кроком, але таким, який задовольнятиме вимоги точності. Від ефективності алгоритму автоматичного вибору кроку значною мірою залежить швидкість виконання усієї програми. Ми величину кроку h у неявному методі Ейлера обирали за емпіричним алгоритмом. На практиці використовують інші, можливо ефективніші методи. Наведемо деякі з них: 1. Метод Брайтона: (»HD де hm, hm+1 - величина т-го та т+1 -го кроку, відповідно; є - допустима локальна похибка обчислень на один крок; ет — вирахувана локальна похибка апроксимації на т-му кроці. Локальну похибку ет апроксимації на т-му кроці вираховують програмним чином за результатами обчислень у попередніх точках згідно з таким алгоритмом: З літератури відомо, що похибку апроксимації явного методу Ейлера можна записати так [109]: є™е=+0.5 h2mx'(F). (8.11.2) Для неявного методу Ейлера:
8. МОДЕЛЮВАННЯ ФІЗИЧНИХ ПРОЦЕСІВ І СИСТЕМ 513 є%ш = -0.5ї,2тх”Є), (8.11.3) Де (т <Т <*и+1. Для визначення єт необхідно оцінити х"(Т) для ґт < 7 < ґт+1. З цією метою можна використати значення вектора змінних стану хт+1, хт, хт_х, віддалених один відносно одного по осі ґ на кт, Ит_{. За цими трьома точками можна побудувати апроксимаційний поліном Ньютона для нерівновіддалених точок: хт~хт-1 *со=*„-і+(*-*-.)(*-оія*'~‘т _‘а~іт-' -(8.11.4) ‘ія *ІЯ-1 *ш+1 ‘ш-1 Якщо з (8.11.4) знайти другу похідну х’(0 і підставити у вирази (8.11.2) та (8.11.3), то можна отримати узагальнену формулу для оцінки величини похибки апроксимації для явного та неявного методів Ейлера [53]: Єт = ~Г~7 [(Хт+1 ~Хт)~"Хт-1)] • (8-11 -5) Пт + Пт-1 т—1 Формула (8.11.5) має простий геометричний зміст: у випадку рівновіддалених точок - це відстань між середньою точкою хт та середньою алгебричною двох крайніх точок хт_х та хт+1. Допустима локальна похибка апроксимації на один крок є або обчислюється програмою за формулою ^ = 0.001х||хтах||? де ||хтах і “ максимально можливе абсолютне значення норми вектора змінних на всьому інтервалі інтегрування, або задається користувачем. Якщо після вирахування ет виявилося, що ет > є, то такий крок вважається хибним і відкидається, величина кроку зменшується за формулою кт+1 - кт к+^є / ет , а розрахунки на т-му кроці повторюють з новим кроком. 17 7-451
514 8.8. Алгоритми автоматичного вибору величини кроку /? 2. Метод трьох зон: У цьому методі наступний (т+7)-й крок визначають так: Ит / 2, якщо \ет | > є; , К+і =-К,якщо [е/£2]<фш|<£; (8.11.6) ккт, якщо |еш|<[г/А:2], де к- порядок точності методу [53]. Результати дослідження засвідчили, що використання методу Брайтона збільшує середню максимальну величину кроку загалом на відрізку інтегрування, зменшує діапазон зміни локальної похибки апроксимації, розташований в околі є, проте спричинює до збільшення загальної кількості відкинутих кроків, які не задовольняють вимогам точності. Метод трьох зон позбавлений таких недоліків, однак спричиняє деяку інертність у реагуванні на зміну величини ет, що передбачає зменшення середньої величини кроку, а, отже, сумарні затрати машинного часу.
9. МОМЕНТИ ІСТОРІЇ ОБЧИСЛЮВАЛЬНОЇ ТЕХНІКИ “Краще раз побачити, ніж багато разів почути” Народна мудрість 9.1. Ера механічних обчислювальних пристроїв Креслення 13-розряд- ного суматора, зроблене рукою Леонардо да Вінчі. Крім креслень, серед рукописів вченого знайдено детальний опис суматора. У 1969 році фахівці фірми ІВМ за цими кресленнями створили працездатний пристрій. Леонардо да Вінчі (1452-1519)
516 9.1. Ера механічних обчислювальних пристроїв (1550-1617) Джон Непер - шотландський математик і теолог у 1614 році винайшов логарифми. Незадовго до своєї смерті, у 1617 році, він винайшов новий спосіб перемноження чисел з допомогою пристрою, названого “паличками Непера”. Теорія обчислень з допомогою цих паличок опубліковано у трактаті “Rabdologiae seu numerationis per virgulas libri duo: cum appendic e de expeditissimo multiplicationis promptuario, quibus accessit et arithmeticae localis liber unus” (Единбург, 1617 p.). Теорія рабдології була першою спробою застосувати для обчислень Вільгельм Шикард ’’Калькулятор” Шикарда (1592-1636) Вільгельм Шикард був професором східних мов Тюбінгенського університету. У 1623 році у листі до Кеплера він повідомляв про шестирозрядну обчислювальну машину, яку винайшов. Машина мала суматор, помножувач і механізм для запису проміжного результату. Дослідники вважають, що машину виготовлено в середині 1623 року. Вона складалась із шестерень, які мали по десять зубців, і однієї однозубої шестерні, яка передавала одиницю в наступний розряд. Якщо шестерні обертали у протилежну сторону, відбувалось віднімання чисел. Результати виконання операцій можна було читати у спеціальних віконцях. Машина та її креслення були загублені і забуті під час Першої світової війни. Однак у 1935 році креслення знайшли... і знову загубили в час Другої світової війни. У 1956 році
9. МОМЕНТИ ІСТОРІЇ ОБЧИСЛЮВАЛЬНОЇ ТЕХНІКИ 517 креслення машини Шикарда заново знайдено! У 1960 році ентузіасти побудували “калькулятор” Шикарда і впевнилися, що він працює. (1623-1662) У 1641-1642 роках у Парижі дев’ятнадцятилітній Блез Паскаль створив “Паскалину”. Ця п’ятирозрядна машина (згодом він створив і восьмирозрядний варіант) використовувала удосконалену ідею Шикарда, однак не могла віднімати і була менш надійною. Проте так трапилося, що про машину Шикарда усі забули, а Паскаль став широко відомий як засновник концепції обчислювальних машин. Він отримав королівську привілею на виготовлення машин, побудував близько 50-ти пристроїв і продав приблизно 10.. 15 штук. Частина з них дійшла до наших днів. Готфрід Лейбниць (1646-1717) Німецький філософ, фізик і математик Готфрід Вільгельм Лейбниць розробив механічну обчислювальну Машину, яку згодом назвали арифмометром. Перший опис “арифметичного інструмента” (арифмометра) зроблено
518 9.1. Ера механічних обчислювальних пристроїв Лейбницем у 1670 році. Арифмометр Лейбниця давав змогу виконати чотири арифметичні дії: додавання, віднімання, множення та ділення, а також добувати корінь квадратний. Починаючи з 1679 року, Лейбниць також розробляв ідею про застосування в обчислювальних машинах двійкової арифметики. Результатом його досліджень став трактат “Expication de I'Arithmetique Binary”, де зазначено, що “обчислення за допомогою двійок (тобто 0 і 1) у винагороду за його складність є для науки основним і породжує нові відкриття, які виявляться корисними згодом, навіть у практиці чисел, а передусім у геометрії: причиною чого слугує та обставина, що при зведенні чисел до простих засад (а саме Oil) усюди виявляється чудовий порядок”. Прогноз Лейбниця збувся тільки через 250 років, коли видатний американський фізик і математик Джон фон Нейман запропонував використовувати саме двійкову систему числення як універсальний спосіб кодування інформації в електронних комп’ютерах. Уільям Севард Барроуз - американський винахідник, творець першого рахункового самописця. Засновник фірми Burroughs. З п’ятнадцятирічного віку заробляв собі на шматок хліба. Хворів туберкульозом. З 1881 року, працюючи в магазині свого батька, Уільям Севард задумав створити рахункову машину, яка б БАРРОУЗ пришвидшувала арифметичні розрахунки. (1855 - 1,898) в 1885 році, за фінансової допомоги фабриканта Томаса Меткафа, Барроуз після декількох невдалих спроб створив машину-суматор. Дані в машину Барроуза вводили з клавіатури, а результат обчислень потрапляв на паперову стрічку. В 1886 році Барроуз і Меткаф з двома друзями організували компанію American Arithmometer. Арифмометр Барроуза, запатентований у 1892 році, мав величезний успіх. На жаль, його творець ним майже не скористався. На 43-му році його життя обірвалось. У 1905 році American Arithmometer перетворили у фірму Burroughs Adding Machine, яка впродовж багатьох десятиліть
9. МОМЕНТИ ІСТОРІЇ ОБЧИСЛЮВАЛЬНОЇ ТЕХНІКИ 519 виготовляла засоби обробки даних — від касових пристроїв до потужних ЕОМ. У 1953 році її перейменували в Burroughs Corporation. У 1986 році її об’єднали з корпорацією Sperry. Так виникла фірма Unisys. У XIX ст. у СІЛА перепис населення проводили кожні 10 років. Із зростанням кількості населення це стало досить складним процесом. Розпочалась розробка методів швидшого підведення підсумків. Перемогу у цьому змаганні отримав інженер Табулятор Холерита Герман Холериш. Він створив електричну рахункову машину, табулятор (верхня картинка) та перфоратор (картинка знизу). Дані про кожного мешканця зберігались на особливій перфокарті. Перфоратор Розташування і кількість отворів відповідали таким даним, як вік, сімейний стан і т. д. Карту вставляли в машину, де по ній рухались кінці дротів. Коли дріт потрапляв на отвір, він замикав коло і лічильник зміщувався на одну поділку. Герман Холерит (1860-1929)
520 9.2. Ера електронно-обчислювальних пристроїв 9.2. Ера електронно-обчислювальних пристроїв Американський винахідник та бізнесмен Томас Едісон за 1 С життя оформив на своє ім’я 1093 патенти, які він отримав у США, ^ Великобританії, Франції та Ні¬ меччині. Розробив систему освіт- іуЯо. лення, сконструював патрон і цо- 1 коль з різьбою, запобіжник, ТомасАлва Лампочки електролічильник, поворотний Едісон Свана (1878) та вимикач, рекордер, мегафон, за- (1847-1931) Едісона (1879) лізничне гальмо, лужно- нікеле¬ вий акумулятор, пристрій для запису телефонних розмов та ін. Ввів у практику паралельне з’єднання ламп, побудував надпотужні електрогенератори. У 1881 році запустив у експлуатацію першу теплову електростанцію. У 1878 році Джозеф Сван (1828— 1914) з Англії винайшов електричну лампочку у вигляді скляної колби з вугільною ниткою розжарення. Щоб нитка не перегорала, Сван видалив з колби повітря. Наступного року Едісон, незалежно від Свана, винайшов лампочку і започаткував їхнє виробництво і продаж. Згодом Едісон і Сван створили спільну компанію “Едісон енд Сван Юнайтед Електрик Лайт компанГ. У 1883 році, експериментуючи з лампою, Едісон ввів у вакуумний балон платиновий електрод, подав напругу і, на своє здивування, зрозумів, що між електродом і вугільною ниткою протікає струм. Так було винайдене явище термоелектронної емісії, яке одержало Англійський фізик Джон Амб- роз Флемінг, досліджуючи ’’'‘ефект Едісона” та відкриття Томпсона, у 1904 р. винайшов і запатентував “випрямляч” або двоелектродну електронну лампу - “діод Флемін- га”. Пристрій спочатку використали у приймачах як детектор радіохвиль. У лампових машинах діод застосували в логічних схемах. назву “ефект Едісона”. Джон Флемінг (1849-1945) ДІОД Флемінга
9. МОМЕНТИ ІСТОРІЇ ОБЧИСЛЮВАЛЬНОЇ ТЕХНІКИ 521 Перша лампова ЕОМ EN1AC Джон Атанасоф (4.10.1903-15.07.1995) у молодому й у похилому віці Джон Вінсент Атанасоф, американський вчений болгарського походження, у 1937 році, отримавши фінансову підтримку компанії “Research Corporation”, разом зі своїм аспірантом Кліфордом Бері розпочав розробку лампової ЕОМ для розв’язання систем алгебричних рівнянь, яка працювала у двійковій системі числення. У 1939 році машину створено і названо ABC (Atanasoff Berry Computer). У зв’язку з війною автори патент на свій винахід не отримали і в 1942 році роботи було призупинено. Починаючи із 1943 по 1946 роки, виконуючи замовлення міністерства оборони СІЛА, їхні ідеї продовжили і завершили два інші американські вчені із Гарвардського університету - Джон Преспер Екерт (9.04.1919-3.06.1995) і Джон Уільям Моучлі (30.08.1907-8.01.1980). 13 лютого 1946 року вони продемонстрували першу в світі лампову цифрову ЕОМ ENIAC (Electrical
522 9.2. Ера електронно-обчислювальних пристроїв Numerical Integrator and Calculator), призначену для розв’язання задач балістики. Це був пристрій вагою понад ЗО тонн, об’ємом 85 м3, який налічував 17468 електронних ламп, 80000 інших компонент, з них - 6000 ручних перемикачів. Машина займала площу 170 м2, споживала 150 кВт/год електроенергії. Працюючи з тактовою частотою 100 кГц, вона могла виконати 5000 операцій додавання або 300 операцій множення за секунду. Її оперативна пам’ять налічувала 20 акумуляторів, з’єднаних між собою магістралями даних і програмними лініями для синхронізації. Кожен акумулятор зберігав десятирозрядне число і один знаковий біт. Константи зберігались у 104-х 12-розрядних регістрах, 100 з них мали пряму адресацію. Уведення програми здійснювали з допомогою панелі перемикачів впродовж тижня часу. Машина працювала 9 років, аж до 1955 року. Американські вчені з компанії “Bell Telephone Laboratoriesінженер, керівник групи фізиків Уільям Бредфорд Шоклі (13.02.1910-12.08.1989), фізики Уолтер Браттейн (10.02.1902- 13.10.1987) і Джон Бардин (23.05.1908- 30.01.1991) 23 грудня 1947 р. завершили роботу зі створення транзистора. Це був точково-контактний пристрій, у якому три металеві дротики контактували з бруском полікристалічного германію. 1 липня 1948 р. на сторінках “Нью- Йорк Тайме” вони оприлюднили своє відкриття, а в 1956 р. за нього отримали Нобелівську премію. У 1954 р. компанія Texas Instruments оголосила про початок промислової розробки транзисторів, а через рік Уільям Шоклі заснував в Пало-Альто (Каліфорнія) фірму Shockley Semiconductor. Транзистор був у 40 раз меншим за електронну лампу, працював швидше, виділяв значно менше тепла, що спричинило бурхливу розробку на його основі ЕОМ нового покоління. До речі, Джон Бардин, один із винахідників транзистора, президент Американського фізичного товариства (1968-1969 pp.), у 1972 році разом із Леоном Купером і Джоном Шрифером за свої роботи з теорії надпровідності отримав Нобелівську премію вдруге, ставши єдиною у світі людиною, яка отримала цю нагороду з фізики двічі.
9. МОМЕНТИ ІСТОРІЇ ОБЧИСЛЮВАЛЬНОЇ ТЕХНІКИ 523 11 листопада 1971 р. фірма Intel (заснована у 1968 р. як виробник напівпровідникових елементів пам’яті) створила перший у світі мікропроцесор - 4004. Історія’ його появи така. Японська компанія Busicom, яка виготовляла калькулятори, замовила Intel’у комплект із 12-ти спеціалізованих логічних мікросхем для серії високопродуктивних калькуляторів. Тед Хофф молодший (1937 р. н.), запропонував усі функції об’єднати в одному мікрокомп’ютерному наборі - мікросхемі. Ідею підтримав Боб Нойс. Японці спочатку заперечували цю розробку, проте в жовтні 1969 року вони зрозуміли переваги ідеї Хоффа. Так виник “комп’ютер на чіпі”. Перша його версія із серйозними помилками з’явилась у січні 1971 року. Тільки 15 листопада 1971 року Intel сповістила світ про народження мікропроцесора, який мав характеристики, що були сумірними з характеристиками ENIAC. Це був 4-розрядний МП, який на площі 3,8x2,8мм містив 2300 /7-канальних МОН-транзисторів. Він працював на тактовій частоті 108кГц, забезпечував адресування 4Кб ПЗП і 512 байт ОЗП і коштував “всього” $300. Через дев’ять місяців Intel викупила в Busicom права на чіп за $60 000. Клод Елвуд Шенон народився в США (штат Мічиган). У 1936 році закінчив Масачусетський технологічний інститут. У 1940 р. довів, що роботу реле в електричних схемах можна задавати з допомогою операцій математичної логіки, що було революційним відкриттям. У 1941 році Клод Шенон почав працювати в Bell Laboratories: займався розробкою систем криптографії. Це допомогло йому відкрити методи кодування з корекцією помилок. Працюючи над передачею даних телеграфними лініями, розробив теорію інформації. У працях 1948-1949 років дав визначення кількості інформації через ентропію - величину, яку використовували в термодинаміці як міру невпорядкованості системи. За одиницю інформації прийняв те, що потім назвали “біт”, тобто вибір одного з двох рівноімовірних варіантів. Клод Елвуд Шенон (1916-2001)
524 9.2. Ера електронно-обчислювальних пристроїв У 1985 р. старенький Клод Шенон несподівано відвідав Міжнародний симпозіум з теорії інформації. На бенкеті він підписав сотні автографів для ошелешених інженерів і вчених, що стояли до нього в довгій черзі. Очевидці говорили, що всі переживали такі почуття, які відчули б фізики, якби до них на конференцію прибув сер Ісак Ньютон. Фредерік Брукс Американське видання Радянське видання 1975 р. 1979 р. Фредерік Брукс - професор університету Північної Кароліни (СІЛА) з 1964 року керував розробкою операційної системи 08/360. У своїй книзі проаналізував різні аспекти як системного, так і прикладного програмування. Його спостереження і висновки не втратили актуальності і сьогодні.
ЛІТЕРАТУРА 1. Абрамов С Л., Гнездилова Г.Г. и др. Задачи по программированию. — М.: Наука, 1988. 2. Алексеев А., Евсеев Г. и др. Новейший самоучитель работы на компьютере. — М.: Десс, 1999. — 654 с. 3. АлкокД. Язык Паскаль в иллюстрациях. — М.: Мир, 1991. — 192 с. 4. Амосов АА., Дубинский ЮА., Котенова Н.В. Вычислительные методы для инженеров: Учеб. пособие. — М.: Высшая школа, 1994. — 544 с. 5. Арашунян О.Б., Залеткин С.Ф. Численное решение обыкновенных дифференциальных уравнений на Фортране. — М.: Изд-во МГУ, 1990. - 336 с. 6. Аррилига Дж. и др. Гармоники в электрических системах. — М.: Энергоатомиздат, 1990. — 320 с. 7. Архипенков С. Психология управления программными проектами. 2004 // www.citforum.ru/SE/project/psychology/ 8. Ахо А., Хопкрофт Дж., Ульман Дж. Построение и анализ вычислительных алгоритмов. — М.: Мир, 1979. — 536 с. 9. Баас Р., Фервай М., Гюнтер X. Бе1рЫ 4: Полное руководство. - К.: ВНУ, 1998. - 800 с. 10. Блехман ИЛ., Мышкис АД., Пановко Я.Г. Прикладная математика: предмет, логика, особенности подходов. — К.: Наукова думка, 1976. — 270 с. И. Боглаев Ю.П. Вычислительная математика и программирование. — М.: Высшая школа, 1990. — 544 с. 12. Божокин С.В., Паршин ДА. Фракталы и мультифракталы. Ижевск: НИЦ “Регулярная и хаотическая динамика”, 2001. - 128 с. 13. Бородич Ю.С., Валъвачев А.Н., Кузьмич АЛ. Паскаль для персональных компьютеров: Справ, пособие. - Мн.: Вышэй- шая школа, 1991. — 365 с. 14. Брукс мл. Ф.П. Как проектируются и создаются программные комплексы. Мифический человеко-месяц. Очерки по системному программированию. — М.: Наука, ГРФМЛ, 1979. - 151 с.
526 15. Бурсиан Э.В. Задачи по физике для компьютера: Учеб. пособие для студентов физ.-мат. пед. ин-тов. — М.: Просвещение, 1991. - 256 с. 16. Буч Гради. Объектно-ориентированный анализ и проектирование с примерами приложений на C++. — 2-е изд. — М.: БИНОМ, 2001. - 560 с. 17. Ван ТасселД. Стиль, разработка, эффективность, отладка и испытание программ. — 2-е изд., испр. — М.: Мир, 1985. — 332 с. 18. Волков Е.А. Численные методы. — М.: Наука, ГРФМЛ, 1982. - 256 с. 19. Гласс Р., Нуазо Р. Сопровождение программного обеспечения. — М.: Мир, 1983. — 156 с. 20. Голуб Ален И. С и C++. Правила программирования. — М.: БИНОМ, 1996. - 272 с. 21. Горинштейн А.М. Практика решения инженерных задач на ЭВМ. — М.: Радио и связь, 1984. — 232 с. 22. Горинштейн А.М. Численное решение задач радиотехники и техники связи на ЭЦВМ. — М.: Связь, 1972. — 200 с. 23. Гринчишин Я.Т. TURBO PASCAL: Чисельні методи в фізиці та математиці: Навч. посібник. - Т., 1994. — 121 с. 24. Грис Д. Наука программирования. — М.: Мир, 1984. — 416 с. 25. Грицюк Ю.І. Обчислювальна техніка, алгоритмізація і програмування мовою Pascal. — K.: ІСДСО, 1995. — 255 с. 26. Грызлов В.И., Грызлова Т.П. Турбо Паскаль 7.0. — М.: ДМК, 1999.-400 с. ' 27. Гулд X., ТобочникЯ. Компьютерное моделирование в физике: В 2-х ч. - М.: Мир, 1990. - Ч. 1. - 349 с. 28. ГулдХ., ТобочникЯ. Компьютерное моделирование в физике: В 2-х ч. - М.: Мир, 1990. - Ч. 2. - 400 с. 29. Гусева А.И. Учимся программировать: Pascal 7.0. Задачи и методы их решения. — 2-е изд., перераб. и доп. — М.: Диалог- МИФИ, 1999. - 256 с. 30. Гутпер P.C., Полунов ЮЛ. От абака до компьютера. — 2-е изд., испр. и доп. — М.: Знание, 1981. — 208 с. 31. Данилюк О. Решить задачу — раз плюнуть // Домашній комп’ютер — 2003. — №3(226). 32. Демидович Б.П., Марон И.А., Шувалова Э.З. Численные методы анализа. — М.: Наука, 1967. — 526 с.
527 33. Демидович П.Д., Марон И.А. Основы вычислительной математики. - 4-е изд., испр. — М.: Наука, 1970. — 664 с. 34. Дияк І.І. Пропедевтика прикладного програмування. — K.: ІСДСО, 1994. - 176 с. 35. Довгаль С.И., Литвинов Б.Ю., Сбитнев А.И. Персональные ЭВМ. Турбо Паскаль V 6.0, объектное программирование, локальные сети. — К., 1993. — 304 с. 36. Епашеников А., Епашеников Е. Программирование в среде Turbo Pascal 7.0. — 3-є изд. — М.: Диалог-Мифи, 1996. — 288 с. 37. Жалдак M.I. Комп’ютер на уроках математики: Посібник для вчителів. — K.: Техніка, 1997. — 303 с. 38. Зализняк В.Е. Основы научных вычислений. Введение в численные методы для физиков. — М.: Едиториал УРСС, 2000. - 296 с. 39. Зубков С.В. Assembler. Для DOS, Windows и Unix. — М.: ДМК, 1999. - 640 с. 40. Инженерные расчеты на ЭВМ: Справочное пособие / Под ред. В.А. Троицкого. — Л.: Машиностроение. Ленингр. отд- ние, 1979. — 288 с. 41. Информатика. Базовый курс / Симонович С.В. и др. — СПб: Питер, 1999. — 640 с. 42. Йодан Э. Структурное проектирование и конструирование программ. — М.: Мир, 1979. — 415 с. 43. Калиткин Н.Н. Численные методы. — М.: Наука, 1978. 44. Каханер Д., Моулер К., Неш С. Численные методы и программное обеспечение. — М.: Мир, 1998. — 575 с. 45. Климова Л.М. PASCAL 7.0. Практическое программирование. Решение типовых задач. — М.: КУДИЦ-ОБРАЗ, 2000. - 496 с. 46. Ковалюк Т.В. Основи програмування. — K.: BHV Киев, 2005. - 400 с. 47. Козин A.C., Лященко H.Я. Вычислительная математика: Пособие для факультативных занятий в 10 классе. — К.: Рад. школа, 1983. — 191 с. 48. Коновалов А.Н. Введение в вычислительные методы линейной алгебры. — Новосибирск: ВО “Наука”. Сибирская издательская фирма, 1993. — 159 с. 49. Коссак О., Тумашова О., Коссак О. Методи наближених обчислень: Навч. посібник. — Львів: Бак, 2003. — 168 с.
528 50. Краскевич В.Е., Зеленский В.И., Гречко В.И. Численные методы в инженерных исследованиях. — К.: Высшая школа, 1986. - 263 с. 51. Кроуфорд Ф. Берклеевский курс физики. — X 3: Волны. — М.: Наука, 1971. - 526 с. 52. Кроновер Р.М. Фракталы и хаос в динамических системах. Основы теории. — М.: Постмаркет, 2000. — 352 с. 53. Кузьмин П.К., Маничев В.Б. Автоматизация функционального проектирования / Под ред. И.П. Норенкова. — М.: Высшая школа, 1986. — 144 с. 54. Культин Н.Б. Программирование в ТР 7.0 и Delphi. — СПб.: БХВ-Санкт-Петербург, 1999. — 240 с. 55. Курс физики: Практикум / Бабич И.А., Гриценко Ю.И. и др. — К: Высшая школа, 1992. — 399 с. 56. Левин А. Самоучитель работы на компьютере. — М.: Нолидж, 1999. — 656 с. 57. Литер Р., Миллс X., Уитт Б. Теория и практика структурного программирования. —М.: Мир, 1982. — 406 с. 58. Лозинсъкий А., Мороз В., Паранчук Р., Паранчук Я. Microsoft Qbasic: програмування та розрахунок динаміки електроприводів. — Львів: Вид-во Нац. ун-ту “Львівська політехніка”, 2001. — 276 с. 59. Макконнелл Дж. Основы современных алгоритмов. — 2-е изд., доп. — М.: Техносфера, 2004. — 368 с. 60. Макконнелл С. Остаться в живых. Руководство для менеджера программных проектов. — СПб.: Питер, 2006. — 240 с. 61. Макконнелл С. Совершенный код. Мастер-класс. — СПб.: Питер, 2005. — 896 с. 62. Мак-Кракен Д., Дорн У. Численные методы и программирование на Фортране. — М.: Мир, 1977. — 584 с. 63. Мандельброт Б. Фрактальная геометрия природы. — М.: Ин-т компьют. исследований, 2002. — 656 с. 64. Март мл. Цифровой спектральний анализ и его приложения. — М.: Мир, 1990. — 584 с. 65. Марченко А.И., Марченко Л.А. Программирование в сдрде Turbo Pascal 7.0. — К.: ВЕК+; М.: Бином Универсал, 1998. — 496 с. 66. Мейер Б., Бодуэн К. Методы программирования: В 2 т. — М.: Мир, 1982. - Т. 1. - 356 с.
529 67. Мейер Б., Бодуэн К. Методы программирования: В 2 т. — М.: Мир, 1982. - Т. 2. - 368 с. 68. Морозов АД. Введение в теорию фракталов: Учеб. пособие. — Нижний Новгород: Изд-во Нижегородс. ун-та, 1999.- 140 с. 69. Мочульский Ю.С., Синицкий JI.A. Программа анализа нестационарных и установившихся режимов диоднотранзисторных схем // Вопросы радиоэлектр. Серия общетехнич. — 1976. — Вып. 2. — С. 37-42. 70. Мудрое А.Е. Численные методы для ПЭВМ на языках Бейсик, Фортран и Паскаль. — Томск: МП “ПАСКО”, 1991.-272 с. 71. Мэтьюз Джон Г., Финк Куртис Д. Численные методы. Использование MATLAB. — 3-є изд. — М.: Изд. дом “Вильямс”, 2001. — 720 с. 72. Немнюгин С A. Turbo Pascal. — СПб.: Питер, 2000. — 496 с. 73. Немнюгин CA. Turbo Pascal: Практикум. — СПб.: Питер, 2000. - 256 с. 74. Нортон П., Джордейн Р. Справочник пользователя IBM PC. — М.: Компютер, 1995. — 526 с. 75. Ортега Д., Рейнболдт В. Итерационные методы решения нелинейных систем уравнений со многими неизвестными. — М.: Мир, 1975. — 558 с. 76. Пестриков В.М., Маслобоев А.Н. Turbo Pascal 7.0. Изучаем на примерах. — 2-е изд., перераб. и доп. - СПб.: Наука и техника, 2004. — 368 с. 77. Пильщиков. В.Н. Сборник упражнений по языку Паскаль. — М.:, Наука, 1989. 78. Попов В. Б. Turbo Pascal 7.0 для школьников. — М.: Финансы и статистика, 1996. — 464 с. 79. Прайс Д. Программирование на языке Паскаль: Практическое руководство. — М.: Мир, 1987. — 232 с. 80. Практическое руководство по программированию/ Пер. с англ. Б. Мик, П. Хит, Н. Рашби и др.; Под ред. Б. Мика, П. Хит, Н. Рашби. — М.: Радйо и связь, 1986. — 168 с. 81. Райс Дж. Матричные вычисления и математическое обеспечение. — М.: Мир, 1984. — 264 с. 82. Ракитский Ю.В., Устинов С.М. и др. Численные методы решения жестких систем. — М.: Наука, ГРФМЛ, 1979. — 208 с.
530 83. Ричи О'Бауэр. Программирование как высшая форма творчества. 1997 // www.bugtraq/ru/library/nüsc/creative.html 84. Самарский АЛ. Введение в численные методы. — М.: Наука, 1987. - 288 с. 85. Самарский АЛ., Гулин А.В. Численные методы. - М.: Наука, 1989. - 432 с. 86. Сергиевский М.В., Шалашов А.В. Турбо Паскаль 7.0. М.: Машиностроение, 1994. — 254 с. 87. Сердюченко В.Я. Розробка алгоритмів та програмування мовою TURBO PASCAL: Навч. посібник для техн. вузів. — X.: ВКП "ПАРИТЕТ" ЛТД, 1995. - 352 с. 88. Скляревский Е. Ребята, пишите программы! 2001 // www.sources.ru/pascal/articles/6846.htm 89. Современные численные методы решения обыкновенных дифференциальных уравнений / Под ред. Дж. Холла и Дж. Уатта. — М.: Мир, 1979. — 312 с. 90. Соколенко П. Pentium глазами программиста // www.wasm.ru /article.php?article= 1011001 91. Словарь иностранных слов. — 7-е изд., перераб. - М.: Русский язык, 1979. — 624 с. 92. Степаненко О.С. Персональный компьютер: Учебный курс. — М.: Вильямс, 1999. — 432 с. 93. Стренг Г. Линейная алгебра и ее применения / Пер. с англ. - М.: Мир, 1980. - 454 с. 94. Турбо Паскаль 7.0. — Изд. 3-є. — K.: BHV, 1996. — 448 с. 95. Турчак Л.И. Основы численных методов: Учеб. пособие. - М.: Наука, ГРФМЛ, 1987. - 320 с. 96. Успенский В А., Семенов АЛ. Теория алгоритмов: основные открытия и приложения. — М.: Наука, ГРФМЛ, 1987. — 288 с. 97. Фаронов В.В. Программирование на ПЭВМ в среде Турбо- Паскаль. — М.: Изд-во Моск. ун-та, 1990. — 526 с. 98. Фаронов В.В. Турбо Паскаль 7.0. Практика программирования: Учеб. пособие. — М.: Нолидж, 1999. — 432 с. 99. Федоренко Р.П. Введение в вычислительную физику: Учеб. пособие для вузов. — М. Изд-во Моск. физ.-техн. ин-та, 1994. - 528 с. 100.Федоров А. Особенности программирования на Borland Pascal. — K.: Диалектика, 1994. — 656 с. 101 .Фигурнов В.Э. IBM PC для пользователей. — Изд. 6-е, перераб. и дополн. — М.: ИНФРА-М, 1995. — 432 с.
531 102. Форсайт Дж., Малькольм М., Моулер К. Машинные методы математических вычислений. — М.: Мир, 1980. — 280 с. 103. Форсайт Дж., Молер К. Численное решение систем линейных алгебраических уравнений. — М.: Мир, 1969. — 168 с. ІОА.Хармутп X. Применение методов теории информации в физике. — М.: Мир, 1989. — 344 с. 105.Хвищун І.О. Методи і алгоритми комп’ютерної обробки експериментальних результатів: Навч.-метод. посібник з курсу "Програмування і математ. моделювання". — Львів, 1998. - 43 с. 106.Хемминг Р.В. Численные методы для научных работников и инженеров. — М.: Наука, ГРФМЛ, 1972. — 400 с. 107.Худсон Д. Статистика для физиков. — М.: Мир, 1967. — 242 с. 108.Цегелик Г.Г. Чисельні методи: Підручник. — Львів: Видавничий центр ЛНУ імені Івана Франка, 2004. — 408 с. 109. Чуа Л.О., Пен-Мин Лин. Машинный анализ электронных схем: Алгоритмы и вычислительные методы. — М.: Энергия, 1980. - 640 с. 110.Шеиь А. Программирование: теоремы и задачи: Учебн. пособие. - М.: МЦНМО, 1995. - 264 с. Ш.Шрюфер Е. Обробка сигналів: Цифрова обробка дискрети- зованих сигналів: Підручник. — К: Либідь, 1992. — 296 с. 112.Шуп Т. Решение инженерных задач на ЭВМ. — М.: Мир, 1982. - 235 с. 113.Chapra С.С., Canale R.P. Numerical Methods for Engineers. Second edition. — McGraw-Hill Company, 1988. — 812 p. 114.Gear C.W. Algorithm 407, DIFSUB for Solution of Ordinary Differential Equations // Commun. Ass. Comput. Math. — 1971. - Vol. 14. - N. 3. - P. 185-190. WS.Shichman H. Integration System of a Nonlinear Network- Analysis Program // IEEE Trans, on CT. — 1970. — Vol. CT-17. - N. 3. - P. 378-386.
Алфавітний покажчик Algol-60 25,26, 393, 394 Altair 26 AMD 334 AUX 309, 315 Basic 9,26,29, 59 BIOS 304,305,380, 381 Borland Pascal 10,18,55 C++334, 335, 339,397 СЖ-адресація 304 COBOL 25,26 COM1 309,315 CON 315 Debug 62,71,73, 81, 82,190,191 Delphi 59,60, 343, 399 , Destructor 87,405,406 DIFSUB 14 DOS 60,75,77, 81,266,303,305, 308,309 DPT 305 Encapsulation 400 ENIAC 521-523 Eof 323, 327, 328 Eoln 323, 327, 328 FAT 306 FAT-16 302, 305, 308 FAT-32 303, 305 Folder 307 Fortran 25,29,45, 51, 332, 335,393, 396 IBM 360 25 IDE 57,188 Implementation 241-243 Inherited 401 Intel 334, 340, 342, 343, 523 Intel 80x86 240 Interface 87,241 Internet 15,26,256, 333,338, 397 LBA 305 LIFO 347 Linux 14 LOGO 26 LPT1 309,315 ££/-розклад 211 MASM 336, 341,355, 362 MBR 305 Microsoft 26,46,308,336, 399 NTFS 302,303,306 NUL 309, 315 NUMERI 414-417,434,437 Object Pascal 56, 59,343, 397 Pascal 14, 18,25, 54,56,57,399 Pentium 334, 339 PL/1 25,26, 396 Private 401,405,406 Public 401,405,406 Setup 77, 304 Simula 67, 396,397 SmallTalk 397, 398 SVGA 101,341 TASM336, TLINK 341,392 Turbo Pascal 10,57, 59,60
Алфавітний покажчик 533 Uses 88,112 VGA 101,/107,248,260 Virtual 404-406 Visual 25,26, 399 Visual FoxPro 399 ^еб-програмування 25 Автокод 23,24 Адреса логічна 189, 355, 360 - сегмента 97, 345,347,348,352, 356, 359, 362, 375 - фізична 359,360 Адресування базове 345,363 - базово-індексне 364 - індексне 363, 366, 375 - неявне 362,363 - пряме 342 Акумулятор 344, 345, 362, 363, 365, 520 Алгоритм 20,21,27,28,32-35, 38- 49, 52-57 - вибору поточного кроку інтегрування 489 - вибору початкового кроку інтегрування 489,496 -Гауса 216-219,225 - графічний 35, 39 -Ейткена 170,171,435,436 - методу Ньютона 159,235,237, 238,487,488,498 - методу половиннного ділення 194 - методу Рунге-Кутга четвертого порядка точності (РК4) 479,480, 494 - неявного методу Ейлера (НМЕ) 487,495 Алгоритм обчислення визначника 211-213,215 - - коефіцієнтів апроксимацій- ного полінома 462,464 - - коефіцієнтів кубічного сплайна 447-451 - - матриці Якобі 236 Алгоритм описовий 35 - переміщення зображення 267 - побудови головної програми 418 і табулювання апроксимацій- ного полінома 462,464 Алгоритм побудови і табулювання полінома Лагранжа 442,443 - - полінома Лагранжа за методикою Ейгкена 436,438 - - полінома Ньютона 445 - - ряду Фур’є 424-427 Алгоритм табулювання полінома Лагранжа 433 - - полінома Лагранжа, побудованого за методикою Ейткена 436 - - - полінома Ньютона 438 Алгоритм формування і табулювання кубічного сплайна 453 - явного методу Ейлера (ЯМЕ) 494 Алгоритмічна мова 27,34 Ален Пол 26 Алфавіт 27,291,305,311 - мови 27,86 Апроксимування методом найменших квадратів 459 Асемблер 24,25,46, 54, 56, 87,334- 343, 352-391 - формат команд 342 Асемблера система команд 364 Атанасоф Джон 521 Атрактор 247,289,294,295 База даних 272 Базовий крок 489,492 Байт 30,92-95,97,100,240,266, 267,304,319,322 - молодший 353, 357 - старший 362,92 Байтів ланцюжок 375 Бардин Джон 5226 523 Барроуз Уільям 518 Бекус 25,28 Бернулі Іоган 163 БернуліЯків 163 Біт 29 Блок 35-37,43,62,68,69,77,87,144 Блок-схема 35 Браттейн Уолтер 522 Брукс Фредерік 11, 524 Буфер 54,62,67,69,77,100,266, 315,328
534 Вейвлети 289 Вектор 181,183,209 - нев’язки208 - переривань 378,380 Вектора норма 236 Величина 30, 32 Виведення гістограми 257 - гратки 264 - діаграми 257 - дуги 250 - еліпса 250 - заповнених фігур 255 - кола 250 - ламаної 250 -лінії 249 - масштабних поділок 110,261 - піксела 249 - прямокутника 250 - пульсуючого “серця” 284 - тексту 255 - шахової дошки 258 Визначеного інтеграла геометричне тлумачення 164 Визначник матриці 205,206,211- 215,231,430 Виклик середовища ВР 61 Виконання повторне 69,201 - програми покрокове 29, 33, 56, 59,79, 80,190,193,194,197,198 Вимірність масиву 183 ' Вимірювання29,30 Винятки 376 Випробування 21,27,29, 31, 50, 51 Вираз 25,98, - для перегляду 201,202 Виразу відстеження 197 - редагування 198,202 - форматування 202 Відображення інформації 19, ЗО, 31, 107 Візуалізація 247 Вікна активізація 65 - заголовок 65 - закриття 65 - згортання 65 - зміна розміру 63,65 - переміщення 65 - розгортання 65 Вікно 61 - діалогове 62 - повідомлень 62 - редактора 62 Вінчестер 303 Вінчестера доріжка 304 - сектор 304 -циліндр 304 Вірш Ніклаус 14,25,26, 56 Вказівник 84,87, 97,266 - ближній (Near) 354 - дальній (Far) 355 - нетипізований 267 - стека 346 - типізований 267 - файловий 315 Г армоніка 422,424,425,428 Гейтс Біл 26 Генератор випадкових чисел 165, 178,179 Гігабайт 30 Головка записуюча 303 Графік функції 153,424 Да Війні Леонардо 515 Даламбера принцип 472 Даних абстрактні типи 396 Даних ініціювання 355,356, 358 Даних семантичні моделі 397 Дані 19 Дані безпосередні 351 Дані скалярні 352 Дані структуровані 352 Дейкстра Едсгер 136, 331 Декомпозиція 403 Деструктор 87,406 Директива Include 337 - компілятора 114 Директорія 61,75-77,306 Диск жорсткий 303 Дискретизація 413,425 - рівняння 473 Дискримінант 40,125 Диференціальне рівняння 470 - рівняння звичайне 470
Алфавітний покажчик 535 Диференціальне рівняння у частинних похідних 470 Диференціального рівняння інтегрування 470,471,477 - рівняння неявна форма 471 - рівняння порядок 471 - рівняння розв’язок 470 - рівняння форма Коші 471 Діагностика 31 Домен 303 Допомога (Help) 66 Доступ послідовний 182,314 -прямий 182,314 Драйвери графічні 107,108 Еволюційність 49 Едісон Томас 520 Ейлер Леопард 163 Ейткен 169,171, Ейткена алгоритм 438 - методика 435,436 ЕкертДжон 522 Екзабайт 30 Екран користувача 63,194 Екранів перемикання 145,201 Електронно-обчислювальна машина 23,520 Елемент масиву 181,364 Елементарна конструкція 88 Жорсткість 485 Завантаження 29 Завантажувач 27,58, 305 Закон Кірхгофа /7-й 223,472 - Кірхгофа 7-й 472 Заміна тексту 78 Запис {Record) 88,251,272 Запис із варіантами 277 Захист інформації 32 Зберігання інформації 31 Збіжність 13, 157-159,233,234,446 - квадратична 157 Зворотний хід алгоритму Гауса 217, 219 Зетабайт 30 Змінна 90 Змінна величина 32 - глобальна 120 - з індексом 182 -локальна 120 - структурована 181 Зміщення {offset) 351,366 Значення величини 91,170,478, Ідентифікатор 32, 88, 183, 191,192, 197 Ідентифікування 31,469 Ім’я довге 310 - змінної 88,273 -коротке 310, 311 -логічне 313,315 Індекс 182-184 Індексу діапазон зміни 183 Ініціалізація 185,298 - графічного режиму 248 - модуля 241,243 Інкапсулювання 399-401 Інтеграл визначений 162 - кратний 165* 179 -Рімана 163 Інтеграла обчислення 164 Інтегроване середовище 188 Інтегрування крок 475,478,479,489, 491 -межі 164,175 - порядок точності 482,484, 513 - чисельне 164 Інтервал інтегрування 165,168, 172 - інтегрування елементарний 167 Інтерполювання 415,417,429 - вузол 429 - глобальне 430,440 - локальне 430,435 - похибка 430 - сплайнами 165,446-450 Інтерполянта 429 Інтерпретатор 26-29, 58, 398,415 Інтерфейс 15,16,45,47,49 Інформатика 19,30 Інформаційне середовище 19 Інформація 20,29,43, 81,84,189, 191,305 - налагоджувальна 191,192 Історія мови Pascal 56
536 Ітераційний процес 129,141,157, 158 Ітерація Ньютона 157,159 Иотабайт ЗО Каталог 245, 346, 307, 308, 310, 311, 313 -поточний 416 Кемені Джон 26 Керування рухом зображення 270 Кілобайт 30 Кластер 306, 307 - втрачений 306 Ключові слова 28,66,84-88 Код операції 362 Колір графічного об’єкта 109,248 Команда 336, 337,338, 340,342,364 - перивання 376 -порожня 381 Команди арифметичні 367 - безумовних переходів 370 - введення-виведення 365 - віднімання 367 Команди ділення 367 - додавання 367 - загального призначення 364 - зовнішньої синхронізації 381 - зсувів 369 * - логічні 369 - множення 367 - передачі управління 370 - переміщення 364 - переміщення курсора 67 - переривань376 - пересилання адреси 365 - пересилання прапорців 365 -побітові 369 - роботи з блоками 67,68 - розширення знака 367 - рядкові 374 -управління 381 Команди управління прапорцями 381 - управління циклами 372 Коментар 46, 50 Компілятор 24,25,27' 28,29,40, 56- 60 - командного рядка 80,189 Компілятора директива 114,390 Компонента масиву 182,185,274, 280 Константа 88, 90, 103,112,166,235, 256,280 - Ліпшиця 475 - типована 185 Конструктор 87,406 Контролер переривань 378 Контрольна точка 62, 193, 195, 196 Контрольний член 482 Копроцесор 94,114, 383 Копроцесора команди 385 - команди алгебричні 389 - команди арифметичні 387 - команди завантаженню! у стек 387 - команди переміщення даних 385 - команди порівняння 383,389 - команди трансцендентні 386 - регістри 385 - типи даних 383 Коректність задачі 136,230, Корекція 368,487,488,524 Кореня локалізація 150 Користувач 194,195,197,201 Корінь рівняння 41,134,149 - рівняння кратний150 - рівняння простий 150 Кох Гельга 292,293 Коші задача 471,473,475 Коші Огюстін 163 Коші-Ліпшиця умова 232,233 Крамер Георг 205,207 Криволінійна трапеція 161 Крок базовий 492 - інтегрування 475,478,479,489, 491 Кроковість методу 475 Курсор 62,64,65 - графічний 249 Курсор текстовий 105 Курсора команди переміщення 249 Курц Томас 27
Алфавітний покажчик 537 Лагранж Жозеф 163 Лагранжа поліном 431 Лейбниць Готфрід 163 Лексичний аналіз 28 Лінеаризація 156,233 Лінкер 27, 83. Лінкування 29 Ліпшиця константа 475 -умова 232,233,475 Лічба ЗО Макроасемблер 336 Макрозасіб 336 Мандельброт Бенуа 291 Масив 181 - багатовимірний 183 - одновимірний 183 Масиву вимірність 183 - елемент 181, 364 - ім’я 183 -компонента 181 -опис 183 - опис текстового 184 Масштабна подібність 289 Масштабування даних 109,181 - коефіцієнт 110,260,262,264 Матриці визначник 205,206,211- 215,231,430 - обумовленість 205,207,209,230, 476 -розмір 181,183 Матриця 183 - верхня трикутна 224 - вироджена 207,208,227,234,236 - вадратна 181,205,207,210,211, 454 - нижня трикутна 210 - симетрична 460 - тридіагональна 449,450,452,454 - Якобі 475,485,487,488,492,497 Мегабайт 30 Меню 59-62,68,70,71 - правила використання 74 Мерсона метод 483-485 Метал інгвістична символіка 28 Метод апроксиму вання 459 -Брайтона 512 Метод виключення 205 - віддзеркалень 207 -Гауса 216-219,225 -Гіра 146,511 - дотичних (Ньютона) 156 - Ейлера неявний 487, 502,510 - Ейлера явний 476 - інтерполювання 429-454 - ітераційний 130, 141,157, 158, 159 - Крамера 207 - лівих прямокутників 166 - Мерсона 483-485 -Монте-Карло 177-180 - Ньютона (дотичних) 156 - Ньютона модифікований 158 - Ньютона розв’язання нелінійних рівнянь 156 - об’єктний 393-410 - обертань 207 - ортогоналізації 207 - парабол (Сімпсона) 172 - половинного ділення 151 - половинного ділення алгоритм 154 - половинного ділення особливі випадки 152 - половинного ділення програма 155 - половинного ділення рекурсивний 134 - правих прямокутників 166 - прогонки 449,454 - простої ітерації 232 - розтягнутий (<extended) 510 - Рунге-Кутта 479,480,494 - сингулярного розкладання 208 - спектральний 417,422, -трапецій 171 -трьох зон 513 - Фельберга 484 - центральних прямокутників 166— 168 - чисельний 210,230,473,475,476, 488,511 -Шичмена 511 Методи Адамса 510 - багатокрокові 510
538 Метода Гауса-Кристофеля 165 -Гіра 511 -імовірнісні 165 - квазіньютонівські 238 - найвищої алгебричної точності 165 - Ньютона-Котеса 165 -прямокутників 166 - розв’язання нелінійних рівнянь 149,156 -спеціальні 165 - сплайнові 165,446-450 -чисельного інтегрування 164 Мінор 210,211,225 Мітка 87, 390,112 Мнемоніка 24, 332,342 Мова 23 - алфавіт 86 - програмування 17,27, 58,115, 140,397 - - високого рівня 24,25,28,35, 45, 58 Мода 422 Моделі математичної економічність 472,473 - - точність 472,473 Моделі математичної універсальність 472,473 Модель 473,465,467 Модель аналітична 468 Модель детермінована 468 Модель імітаційна 468,469 Модель масштабна 466 - математична 468 - на макрорівні 472 - на мікрорівні 471 - молекулярної динаміки 469 - натурна 466 - обчислювальна 466 - регресійна 469 - стохастачна 468 - фізична 466 Модель-аналог 467 Моделювання 465 - динамічного режиму 507 Модифікація змінних 199 Модуль (Unit) 240 Модуля створення 241-243 Монте-Карло метод 177-180 Моучлі Джон 522 Надійність 21 Накопичувач 303 Налагодження 116,188 - із зупинками 195 Налагоджувач вбудований 57,58, 83,190,192,195 Написання програми 14,46,188, 328, 341,395 Нейман Джон 178, 518 Непер Джон 516 Не-число 384 Нойс Боб 523 Норма вектора 208,236 Носій інформації 31 Об’єкт 11,14,25,29, 30-32,397 Об’єкта створення 404 Об’єктний код 28,29,342 Обертання зображень 285-287 Обробка даних 19 -інформації 31 Обробник переривань 378-380 Обумовленість матриць 205,207, 209,230,476 Обумовленості число 231 Обчислювальна математика 16-18, 25,209 Одержання інформації 30 Оперативна пам’ять 266,302,315, 359, 522 Оператор 26-28, 36 -Case 139 -For 141-145 -Repeat 148 - While 146-147 - With (приєднання) 275 - безумовного переходу 135,370 -введення 100 - виведення 100 - виклику процедури 116 -присвоювання 135 -складений 113, 135,137,142 - умовний Case (вибору) 139 - умовний If (розгалуження)
Алфавітний покажчик 539 - умовний вкладений 138 Операції арифметичні 339 - логічні 95 Операцій пріоритет 98 Опис змінної 113 -масиву 183 - мови 27 - процедури 117,199 -текстового масиву 184 -файлу 312 - функції 124 Опції 71, 82 Опції-діалоги 72 Осі координат 110,262 Осі координат плаваючі 261 Оцінка похибки апріорна 168-171 Пам’яті модель 360 Compact 361 - -Flat361 - - Huge 361 Large 361 Medium 361 Small 361 Tiny 360 - резервування 352,356,357 - сегмент 97,190,266 Пам’яті сторінка 359 Пам’ять д инамічна 266-268 - магнітна 32,303 - оперативна 24,266,302,315,359, 522 Парадигма 60,403 Параметр 29, ЗО, 31, 37, 57,70,71, 81 - фактичний 122,123 - формальний 122 - циклу 37 Паскаль Блез 517 Пейперт Семюел 26 Переваги мови Pascal 55 Перегляд значень 195 Передавання інформації 30, 31 Перемикання екранів 74,145,201 Переривання 349, 351, 376 - апаратне 376 - асинхронне 376 - внутрішнє 376 - зовнішнє 376 - програми 376 Переривання синхронне 376 -точка 195 Переривань система 376 Перетворення Фур’є дискретне 415, 422 швидке 422 Період 422 Періодичний сигнал 344 Петабайт 30 Підпрограма 115,116, 390 - стандартна 126 Піксел 101 Піксела виведення 110 - координати 110 Площа фігури 161 Позначення величини 32 Покрокове виконання 29,33, 56,59, 79, 80,190,193,194,197,198 Поле 198,199,272,273,278 - бітове 355 - порядку 384 Поліморфізм 400,404 Поліном 165,166,172,430 - Лагранжа 431-439 - Ньютона 440-445 Помилка 20,21,34, 54,66,68,78, 80, 90,109 - етапу виконання 189 - компілювання 79,82,188,189 -логічна 190 -семантична 189 - синтаксична 189 Помилки номер 189 Порт 100, 302, 309, 315, 335, 365, 377 Порядок точності методу інтегрування 482,484, 513 Похибка 54,153,157,164-174,179, 207,213,231 -відносна 231, - глобальна 476,477,478, - дискретизації 476 - заокруглення 210,231,476,477 - інтерполювання 430 -обчислень 165,170,179,437, 511 - методу Сімпсона 174 - методу трапецій 172
540 Похибка методу центральних прямокутників 168 -чисельного інтегрування 169 Похибки оцінка 480 Похибки оцінка апостеорна 169,170 Пошук 13,28,30,69,70,73,78,79 -інформації 31 - процедури 200 - тексту 78 Прапорець 204, 305, 348, 351 - вкладеності задачі 349,350 - нуля 349, 350 - парності 349 - перенесення 349 - переповнення 349,350 - переривання 349,351 - системний 349 - стану 349 -трасування 349,351 - управління 349,350 Принтер 75,77,103,107, 302, 309, 315 Принцип самоподібності 289,291 Принципи написання програм 48 Присвоєння 32,36,88, 124,135 Пристрій арифметико-логічний 344 Пристрій логічний 315 - термінальний 100 Прогноз 487,488,490 Прогонки метод 344 * Програма 15,20 -головна 121,221,240,419 - методу Монте-Карло 180 - методу половинного ділення 155 - обчислення інтегралів із заданою точністю 176 Програми виконання 20,29,193,46, 60,66,67,70,79, 80 - заголовок 36,88, 112,114 - керуючі структури 135 - компілювання 28,29,56,60-62, 66,73,79-81 - компонування 73,79-81 Програміст 18,20,24-26, 34,45-57, 72 Програмна інженерія 21 Програмний засіб 25,45,59 Програмування 9,11-16,19 Програмування високого рівня 24, 25 - методологія 26, 56, 399,400 -недоліки 12 Програмування об’єктно- орієнтоване 56,59,60,331, 393 - процедурне 393,394 - радощі 11 - структурне 26, 55, 56, 394,400 - технологія 20,21,22,60,188,393 - філософія 14 Прогресія арифметична 131 Продуктивність програми 53 Простота 48,49,55, 152,155,209, 324 Проходження 135 Процедура 29, 36,37,79,84,87,88, 116 -власна 59,116 - графічна 107,247-257 - з параметрами 122 - завчасного завершення циклу 149 -рядкова 128 - стандартна 116,126 Процедури виклик 36,114,116 -опис 117 - порядкового типу 128 Процедури правила програмування 123 Процес 19-22 - коливний 422 Прямий хід алгоритму Гауса 217— 219 Псевдографіка 103 Псевдокод 34, 35 Радіоактивний розпад 473 Радіус-вектор 285 Регістр 310, 343-349 -^£/385 - акумулятор 344 - арифметичний 344 - базовий 345 - вказівниковий 345 - даних 347 - загального призначення 343 -індексний 345 - копроцесора 385
Алфавітний покажчик 541 Регістр лічильник 345 - прапорців 348, 349 - сегментний 347 - стану 348 - управління 348 Регресія 459 Режим графі*ший 100 - текстовий 100 Рекурсивне дерево 133 Рекурсія 129 Речення 24,27,28, Рівняння компонентне 472 - корінь 149 - лінеаризація 156 - нелінійне розв’язання 149 - розв’язок 149 - топологічне 472 Рітчі Деніс 26 Розв’язок системи 205 Розгалуження 135,136 Розділ операторів 112,113 -описів 112 - опису констант 112 - міток 112 - процедур та функцій 113 - типів даних 113 Розпізнавання 30, 31 Рунге-Кутга метод 479,480,494 Сі 26,46,57 Сван Джозеф 520 Сегмент даних 346,347 -коду 240, 346,347 - стека 346,347 Сегмента зміщення 190,351 Семантика 27,189, 396 Середовище інформаційне 19 - інтегроване 56, 57, 58,60 Серпінський 293,301 Сигнал періодичний 422 Синтаксис 27,28,189,198 Синтаксична діаграма -помилка 46,189 Синтаксичний аналіз 28 Система диференціальних рівнянь 470,471,475 - диференціальних рівнянь жорстка 485,487 Система координат декартова 280, 285 - - екранна 110,111,250,260,267, 288 - лінійних алгебричних рівнянь (СЛАР) 205 - нелінійних рівнянь (СНР) 232 Скінчені різниці висхідні 440,441 Скінчені різниці нисхідні 440 - центральні 441 Слек 307 Слово 353 - ключове 28,87 - подвійне 353 Спектри амплітудний і фазовий 423 Спеціальні ситуації 384 Сплайн 446 - кубічний 446-450 Спольский Джоель 331 Спостереження 11,30,289,461 Стаціонарний режим 476 Стек 62,129,195,196,200,266, 346, 347 - виклику 366,372 Степінь апроксимуючого полінома 165,460,461 Стиль програмування 50 Стійкість 45,208,230,231,294,423, 446,476,478,479 - коефіцієнтна 230 - по правій частині 230 Структура 25,26, 51, 56,60,71, 115, 117,135,138,241,272 - даних 48, 54, 55,88, 91,112,113, 181 - ієрархічна 27,116,398,402 Структурована змінна 91,352, 181 Таблиця віртуальних методів 406 - ідентифікаторів 191 -кодів ASCII 96,103 Таксономія 402 Тамагочі 16 Тейлора ряд 156,167,233,476,477, 479 Тейлорівський розклад 168,476 Тека 307 Тексел 100
542 Тензор 183 Теорема Вейєрпгграса 430 - про Ш -перетворення 225 Терабайт 30 Тестування 20,21,46,47 -програми 54,171 Тетрада 23 Технологія об’єктно-орієнтована 331,397, 399 Тип базовий 92 -текстовий 97 - цілий беззнаковий 354 - цілий зі знаком 354 Типи адресні 91 -даних 90 - скалярні 91 - струкгуровані 91 - дійсні 94 - символьні 96 логічні 95 - цілочисельні 92 Торвсиїьдс Лінус 14 Точка зупинки 202,203 -переривання 195 Транслятор 28,29,58, 332, 395 Трапеція криволінійна 161,164,167, 171,178 Трасування 79,80, 81,193,200 Тріада 23 * Універсальність 25,26, 34,45,46, 48,49,151 Успадкування 400-404 Фазовий простір 294,476 Файл 46, 54,61,302 - двійковий 302, 307 -запис 302, 304,314,324 - логічний 302 - нетипізований 312,321 -перейменування 317, 318 -створення 314 -текстовий 312,323 - типізований 312,320 - фізичний 302 Файла атрибут 308,317-319 - відкривання 315 Файла дата створення 317 - закривання 315 - знищення 317 -ім’я 312 -опис 312, 315 - розширення 308,309 - час створещія 317 -чигання 309, 311, 313-315 Файлова змінна 312 - система 302, 306, 308,310 Файлові операції 314 Фельберга метод 484,485 Фермі Енріко 179 Флемінг Джон 521 Формула другої похідної 160 - квадратичного інтерполювання 431 - лінійного інтерполювання 431 - Ньютона 156-158,234,235 - парабол (Сімпсона) 172 - першої похідної 160 - трапецій Формули диференціюванння назад (ФДН)511 - Ньютона-Котеса 165 -Рунге 169,170 Форсайта теорема 234 Фрактал 289-296 Фракталів використання 289,290 Фрейм 396 Функції 124 - арифметичні 127 -виклик 124,126 - опис 124 - парність 424 -табулювання 118,150,179,262, 263 Функція апроксимуюча 164,165, 459,461 - бібліотечна 193 - інтегрована 162 -первісна 163 - перетворення 127 - періодична 422,425,427 - підінтегральна 163-165,167,169, 172 - порядкового типу 128 -рекурсивна 129,130
Алфавітний покажчик 543 Функція рядкова 128 -стандартна 193 Функція тестова Фур'є Жан Батист 164 Хаос 11,289,290,292 Хвильове число 422 Холерит Герман 519 Хопер Грейс 25 Хофф Тед 523 Центральний процесор 23 Цикл 140 - з відомою кількістю повторень 141 -з параметром 141 - з передумовою 141,146 - з післяумовою 141,148 Частота 422,424,522 Чисельний метод 210,230,473,475, 476,488,511 Число 31, 385 - денормалізоване 384 - дійсне 40,89, 91,92,94 - з плаваючою комою 153,335, 383-385 - запаковане 355 - незапаковане 355 -ціле 51, 89, 92, 324, 328, 354 -, яке не підтримується 384 ШенонКлод 29, 524 Шикард Вільгельм 516 Шоклі Уільям 522 Шрифти графічні 107,111,256
Навчальне видання ХВИЩУН Іван Олександрович Програмування і математичне моделювання Підручник Редактор І. Лоїк Технічний редактор С. Сеник Коректор І. Василяйко, Ю. Печенюк Комп'ютерна верстка: О. Карташова, Т. Мшайленко, І. Хвигцун Обкладинка художника В. Жиборовського Підп. до друку 07.08.2007. Формат 60х90/16 Папір офсетний. Друк офсетний. Ум. друк. арк. 34. Обл.-вид. арк. 34,1. Зам. № 7-451. Видавничий центр Львівського національного університету імені Івана Франка Україна, 79000, м. Львів, вул. Дорошенка, 41 Видавничий Дім “Ін Юре” Україна, 04107, м. Київ, вул. Багговутівська, 17-21 Тел./факс: (044) 537-51-20 537-51-00, 537-51-01 www.shop.inyure.kiev.ua E-mail: info@inyure.kiev.ua, sales@inyure.kiev.ua Свідоцтво про внесення суб’єкта видавничої справи до Державного реєстру видавців, виготівників і розповсюджувачів видавничої продукції. Серія ДК № 2191 від 20.05.2005 р. Віддруковано ВАТ “Білоцерківська книжкова фабрика” Україна, м. Біла Церква, вул. Л. Курбаса, 4.