logo
Лабораторна 4_1_семестр

3.3. Приклад Румпа.

В 1988 р. проф. Зігфрид Румп, співробітник німецького відділення фірми IBM, досліджуючи алгоритми обчислень з гарантованими межами інтервалів, які містять заздалегідь відомий правильний результат, отримав поліном, який за певного співвідношення значень змінних дає однозначно неправильний результат для всіх стандартних форматів чисел з плаваючою комою [3].

, (4.1)

де  = 77617,  = 33096.

Використовуючи різні формати чисел з плаваючою комою на стандартній для того часу великій обчислювальній системі IBM S/370 для даного поліному було отримано приблизно однакові результати:

32 біт: = +1,172604;

64 біт: = +1,1726039400531786;

128 біт: = +1,1726039400531786318588349045201838.

Такі результати позволяють вважати, що надійний результат - приблизно 1,172603, або навіть 1,172603940053. Однак насправді правильний результат (в межах одиниці останньої цифри) відрізняється від продемонстрованих вище не тільки значенням, але навіть і знаком (!):

= -0,827396059946821368141165095479816...

Причиною такої розбіжності є те, що в даному випадку значення та задовільняють простій умові:

, (4.2)

а підставивши це значення в (4.1) маємо:

. (4.3)

Число  = 7917111340668961361101134701524942848 - 37-ми значне. Це означає, що 34-х значущих цифр формату 128 біт недостатньо для того, щоби представити це число точно, тому похибка представлення числа порядку 1000 набагато перевищує число 2. Таким чином ці числа знаходяться в таких діапазонах представлення, здійснення арифметичних дій між числами із яких є некоректним. В результаті виконання дій в форматі 128 біт ми отримуємо

(4.4)

Даний приклад став класичною ілюстрацією тих проблем, які притаманні сучасним обчисленням з плаваючою комою. Обчислення полінома Румпа на комп'ютерах з процесорами Pentium та Sun Sparc дало різний результат в залежності від того, яка система комп'ютерної математики використовувалась.

Наприклад, обчислення полінома Румпа на базі програми, отриманої за допомогою компілятора Fortran 95 фірми Sun Microsystem Inc., дали такі результати:

32 біт: = −6. 338253∙1029;

64 біт: = −1. 1805916207174113∙1021;

128 біт: = +1. 1726039400531786318588349045201838.

Пізніше Румп показав [4], що аналогічні проблеми виникають і в випадку більш простого полінома (за аналогічних значень та ):

(4.5)

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

Одним із способів отримання правильного результату для прикладу Румпа є використання символьних обчислень. В даному контексті це означає, що при обрахунку полінома дійсні числа представляються не в традиційному форматі з плаваючою крапкою, а в вигляді раціональних дробів. В такому випадку поліном Румпа набуває вигляду:

, (4.6)

Якщо для обрахунків використовувати саме таку формулу, наприклад в пакеті Maple 8, то отримаємо правильний результат:

(4.7)

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

Ще одним способом отримання правильного результату є використання під час обчислень такої розрядності представлення даних, яка суттєво перевищує стандартну. Для приклада Румпа 37-ми значне число в формулі (4.3) вимагає бітів для його повного представлення (див. Лабораторна робота №3, розділ 3.3), що є дещо більше, ніж 112+1 біт, який виділяється на мантису в форматі числа з плаваючою комою ІЕЕЕ754 128-біт.

Таким чином ми приходимо до необхідності форматів чисел з довжиною, що перевищує 128 бітів. Сучасні мови програмування можуть працювати з надзвичайно довгими цілими числами, Наприклад клас cBigNumber, який реалізує цілі числа необмеженої розрядності для С++ і в якому передбачені всі стандартні операції мови С++, а за допомогою цілих чисел можна реалізовувати і дійсні числа.

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

Yandex.RTB R-A-252273-3