Якщо ви хочете добре позначити помилку округлення, вам не обов'язково потрібна бібліотека точної точності. Ви можете використовувати аналіз запущених помилок замість цього.
Мені не вдалося знайти хорошого посилання в Інтернеті, але все це описано у розділі 3.3 книги Ніка Хігема "Точність та стабільність чисельних алгоритмів". Ідея досить проста:
- Перефабрикуйте свій код так, щоб у кожному рядку було одне призначення однієї арифметичної операції.
- Для кожної змінної, наприклад
x
, створіть змінну, x_err
яка ініціалізується до нуля, коли x
їй призначається константа.
- Наприклад, для кожної операції, наприклад
z = x * y
, оновіть змінну, z_err
використовуючи стандартну модель арифметики з плаваючою комою, а також результуючі z
та помилки запуску x_err
та y_err
.
- Після цього значення, що повертається, має також відповідне
_err
значення. Це залежно від даних про вашу загальну помилку округлення.
Хитра частина - крок 3. Для найпростіших арифметичних операцій можна використовувати такі правила:
z = x + y
-> z_err = u*abs(z) + x_err + y_err
z = x - y
-> z_err = u*abs(z) + x_err + y_err
z = x * y
-> z_err = u*abs(z) + x_err*abs(y) + y_err*abs(x)
z = x / y
-> z_err = u*abs(z) + (x_err*abs(y) + y_err*abs(x))/y^2
z = sqrt(x)
-> z_err = u*abs(z) + x_err/(2*abs(z))
де u = eps/2
одиниця округлення. Так, правила для +
та -
однакові. Правила будь-якої іншої операції op(x)
можна легко витягнути за допомогою розширення результатів, застосованих до серії Taylor op(x + x_err)
. Або ви можете спробувати googling. Або використовуючи книгу Ніка Хігхема.
Як приклад, розглянемо наступний код Matlab / Octave, який оцінює поліноми в коефіцієнтах a
у точці x
за схемою Хорнера:
function s = horner ( a , x )
s = a(end);
for k=length(a)-1:-1:1
s = a(k) + x*s;
end
Для першого кроку ми розділили дві операції на s = a(k) + x*s
:
function s = horner ( a , x )
s = a(end);
for k=length(a)-1:-1:1
z = x*s;
s = a(k) + z;
end
Потім вводимо _err
змінні. Зауважте, що вхідні дані a
і x
вважаються точними, але ми також могли б також вимагати від користувача передачі відповідних значень для a_err
та x_err
:
function [ s , s_err ] = horner ( a , x )
s = a(end);
s_err = 0;
for k=length(a)-1:-1:1
z = x*s;
z_err = ...;
s = a(k) + z;
s_err = ...;
end
Нарешті, ми застосовуємо описані вище правила, щоб отримати умови помилки:
function [ s , s_err ] = horner ( a , x )
u = eps/2;
s = a(end);
s_err = 0;
for k=length(a)-1:-1:1
z = x*s;
z_err = u*abs(z) + s_err*abs(x);
s = a(k) + z;
s_err = u*abs(s) + z_err;
end
Зауважте, що оскільки у нас немає a_err
або x_err
, наприклад, вони вважаються нульовими, відповідні терміни просто ігноруються в виразах помилок.
Et voilà! Тепер у нас є схема Хорнера, яка повертає залежно від даних оцінку помилок (зверніть увагу: це верхня межа помилки) поряд з результатом.
В якості додаткової примітки, оскільки ви використовуєте C ++, ви можете розглянути можливість створення власного класу для значень з плаваючою комою, який містить _err
термін і перевантажує всі арифметичні операції для оновлення цих значень, як описано вище. Для великих кодів це може бути простіший, хоча і обчислювально менш ефективний, маршрут. Сказавши це, ви можете знайти такий клас в Інтернеті. Швидкий пошук Google дав мені це посилання .
± uх ( 1 ± u )