Якщо ви хочете добре позначити помилку округлення, вам не обов'язково потрібна бібліотека точної точності. Ви можете використовувати аналіз запущених помилок замість цього.
Мені не вдалося знайти хорошого посилання в Інтернеті, але все це описано у розділі 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 )