У мене є числова функція, що f(x, y)
повертає подвійне число з плаваючою комою, яке реалізує певну формулу, і я хочу перевірити, чи правильно воно проти аналітичних виразів для всіх комбінацій параметрів x
і y
що мене цікавить. Який правильний спосіб порівняння обчислених та аналітичні числа з плаваючою комою?
Скажімо, два числа є a
і b
. Поки я переконався, що як абсолютні ( abs(a-b) < eps
), так і відносні ( abs(a-b)/max(abs(a), abs(b)) < eps
) помилки менше, ніж eps. Таким чином він виявить числові неточності, навіть якщо цифри, скажімо, будуть приблизно 1e-20.
Однак сьогодні я виявив проблему, числове значення a
та аналітичне значення b
були:
In [47]: a
Out[47]: 5.9781943146790832e-322
In [48]: b
Out[48]: 6.0276008792632078e-322
In [50]: abs(a-b)
Out[50]: 4.9406564584124654e-324
In [52]: abs(a-b) / max(a, b)
Out[52]: 0.0081967213114754103
Тож абсолютна помилка [50] (очевидно) мала, але відносна похибка [52] велика. Тому я подумав, що у мене в програмі помилка. За допомогою налагодження я зрозумів, що ці числа денормальні . Як такий, я написав таку процедуру, щоб зробити належне порівняльне порівняння:
real(dp) elemental function rel_error(a, b) result(r)
real(dp), intent(in) :: a, b
real(dp) :: m, d
d = abs(a-b)
m = max(abs(a), abs(b))
if (d < tiny(1._dp)) then
r = 0
else
r = d / m
end if
end function
Де tiny(1._dp)
повертається 2.22507385850720138E-308 на мій комп'ютер. Тепер все працює, і я просто отримую 0 як відносну помилку, і все в порядку. Зокрема, вищезгадана відносна помилка [52] є помилковою, вона просто викликана недостатньою точністю денормальних чисел. Чи rel_error
правильна моя функція? Чи потрібно просто перевірити, що abs(a-b)
менше крихітного (= денормальне), і повернути 0? Або я повинен перевірити якусь іншу комбінацію, наприклад
max(abs(a), abs(b))
?
Я просто хотів би знати, що таке "правильний" шлях.
exp(log_gamma(m+0.5_dp) - (m+0.5_dp)*log(t)) / 2
при m = 234, t = 2000. Коли я збільшуюсь, вона швидко переходить до нуляm
. Все, що я хочу переконатися, що мій цифровий режим повертає "правильні" числа (щоб повернути нуль теж прекрасно) принаймні до 12 значущих цифр. Тож якщо обчислення повертає денормальне число, то це просто нуль, і проблем не повинно бути. Тому просто порядок порівняння повинен бути стійким проти цього.