Використання математичного співпроцесора 80x87

Застосування співпроцесора значно збільшує точність математичних розрахунків і прискорює їх виконання. Справа лише в малому - наявності його і умінні використовувати.

Щоб програма могла задіяти можливості співпроцесора, вона повинна в своєму початку мати директиву (ключ режиму компілятора) $ N +:

Режим компіляції $ N + є глобальним і не може змінюватися надалі. При створенні модулів (UNIT), орієнтованих на роботу з співпроцесором, тобто використовують вводяться ним типи, вказівка ​​ключа $ N + в них необов'язково. Важливо лише, щоб він був в головній програмі, що включає в себе ці модулі.

При необхідності відключити співпроцесор повинен вказуватися ключ $ N-. При цьому програма може перестати компілюватиметься (компілятор «забуде» типи чисел з підвищеною точністю).

Якщо в ПЕОМ встановлено співпроцесор, то компілятор сам визначає ключове слово CPU87 для умовної компіляції. Це можна використовувати для автоматичного вибору режиму компіляції:

Наведена вище конструкція визначає, як буде скомпільовано текст - в розрахунку на співпроцесор або без нього.

Після компіляції виконання програми щоразу починається з перевірки наявності співпроцесора і визначення його типу. Результат перевірки записується в зумовлену змінну системної бібліотеки - Test8087 типу Byte (табл. 9.8).

Значення Test8087 Підключений 8087 2 Підключений 80287 3 Підключений 80387

Якщо програма компілювати в режимі, а значення Test8087 вийшло рівним 0, то програма зупиниться з видачею повідомлення про необхідність співпроцесора. Існує, однак, засіб відключити автоматичну перевірку наявності співпроцесора при запуску програми. Треба ввести системну змінну MS-DOS з ім'ям 87 і значеннями Y (від YES - так) і N (від NO - немає). Найкраще це зробити в файлі AUTOEXEC.BAT, вставивши рядок

Значення системної змінної MS-DOS 87, рівне Y, накаже вважати співпроцесор підключеним, а N - відповідно відключеним. Взагалі кажучи, краще не обманювати техніку і програми. Прибережіть цю методику (з SET 87 =) на самий крайній випадок.

Турбо Паскаль дає можливість емулювати роботу співпроцесора програмним шляхом. Це означає, що можна створити програму, яка буде працювати з високою точністю незалежно від наявності співпроцесора. Виявлено співпроцесор - добре, він і буде навантажений, немає співпроцесора - вся точність буде отримана імітацією його. Зрозуміло, що в останньому випадку будуть втрати в часі рахунку, і чималі. Включенням емуляції управляє ключ $ Е. Він має сенс тільки поруч з ключем $ N. Можливі такі їх поєднання:

- підключення бібліотеки для емуляції співпроцесора; при його відсутності точність забезпечується програмно за рахунок швидкості; - програма зможе працювати тільки на машинах з співпроцесором;

і - співпроцесор не використовується, ключ емуляції ігнорується. Програма працює тільки зі звичайною точністю і швидкістю.

Якщо в програму вставлений зовнішній код директивою, то для роботи з співпроцесором цей код повинен бути отриманий з урахуванням використання інструкцій 80X87.

Переваги від використання співпроцесора - це, в першу чергу, швидкість обчислень, яка може вирости в кілька разів. Друга перевага - збільшення точності обчислень з плаваючою точкою. У розрахунку на математичний співпроцесор вводяться типи, наведені в табл. 9.9.

Всі ці типи - речові, за винятком Comp, який є «дуже довгим» цілим типом (зберігає тільки цілі значення). Діапазон цього типу в таблиці заданий округлено, так як реальні числа (від -2 до 263-1) занадто довгі.

Звичайний тип Real (6 байт, діапазон 2.9Е-39. 1.7Е + 38, 11-12 значущих цифр) буде працювати з співпроцесором, але вкрай неефективно. Цей формат - чужий для співпроцесора, і час, «з'їдається» перетворенням його в сопроцессорний тип, перекриває прискорення. А точно не додається. Тому краще всього ввести свій тип, наприклад Float, і розуміти під ним або Real, або чисто сопроцессорний дійсний тип в залежності від режиму компіляції.

d. Array [1..9] of Float;

Цілі типи Турбо Паскаля працюють з співпроцесором без будь-яких застережень.

Особливо важливим є питання точності обчислень. При використанні співпроцесора всі стандартні математичні оператори й функції мови, які повертають зазвичай значення Real, починають повертати значення типу Extended. У зв'язку з цим має сенс спиратися саме на цей тип як базовий. Проте цілком можливо, що в програмі братимуть участь змінні різних типів. У таких випадках при необхідності буде проводитися перетворення значень, а значить, втрата точності. При обчисленні значень правих частин операторів присвоювання результат має точність, збігається з найбільш точним з типів членів виразу (або, що те ж саме, з найбільш ємним типом). Це означає, що в присвоєнні

значення виразу справа буде обчислено як тип Extended. Але при присвоєнні його змінної result «малого» типу Single буде вироблено усічення, і різко зменшиться число значущих цифр після десяткової точки. Подібні ситуації треба передбачити і намагатися уникати їх. Особливо неприємні вони в циклах підсумовування:

for i: = 32767 to 65535 do Sum: = Sum + i / e;

Тут подібні втрати будуть повторені тисячі разів, і накопичена помилка може бути порівнянна з самої сумою. Виправити ситуацію легко: треба ввести додаткову змінну eSum точного типу Extended для суматора, і переписати цикл:

for i: = 32767 to 65535 do eSum: = eSum + i / e;

Тепер втрати будуть значно менше.

З тієї ж причини (через усічення точності) некоректною є операція порівняння двох різнотипних речових змінних або змінної з виразом (останнє, як вже зазначалося, може бути обчислено в типі Extended). Так, порівняння в прикладі:

при формальної правильності та очевидності дасть результат False - помилково, так як d має менше значущих цифр, ніж e. Зазвичай при порівнянні речових значень перевіряють їх збіг, а ступінь розбіжності. Якщо ця ступінь порівнянна з точністю уявлення найбільш грубого числа, то значення можна вважати рівними. Так, умова if в останньому прикладі було б переписати так:

if Abs (d-e) <1.0Е-15 then.

Тут 1.0Е-15 - точність для типу змінної d (Double).

Продовжимо перелік особливостей застосування співпроцесора. Його наявність в ПЕОМ та використання сильно впливає на роботу функції округлення Round: вона починає округляти полуторні значення в бік найближчого парного цілого числа (це називається «банківським способом»)! наприклад:

без співпроцесора з співпроцесором

Round (0.5) -> 1 Round (0.5) -> 0

Round (1.5) -> 2 Round (1.5) -> 2

Round (2.5) -> 3 Round (2.5) -> 2

Round (3.5) -> 4 Round (3.5) -> 4

З іншими значеннями (без '.5') функція працює нормально.

Деякі неприємності можуть чекати любителів рекурсивного підходу до написання функції. Можливі, в принципі, ситуації, коли рекурсивні виклики переповнять внутрішній стек даних співпроцесора, розрахований на вісім рівнів рекурсії, і виникне збій програми. Можливим рішенням буде рознесення сложнорекурсівних виразів типу Fn: = Fn (N-1) + Fn (N-2) по локальних змінних, наприклад, f1: = Fn (N-1); і f2: = Fn (N-2). Після цього вираз Fn: = f1 + f2 буде безпечним для співпроцесора.

Завершуючи тему використання співпроцесора, нагадаємо, що і розширені речові типи, і тип Real при роботі з співпроцесором 80X87 виводяться на друк операторами Write і WriteLn з 4 цифрами в показнику ступеня:

при $ N- WriteLn (123.4) видасть 1.2340000000Е + 02,

але при $ N + WriteLn (123.4) видасть 1.234000000000000Е + 0002.

Цей факт треба враховувати при форматованому виведення і при перетворенні чисел в рядок процедурою Str.

Схожі статті