У мене є числова функція, що 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 значущих цифр. Тож якщо обчислення повертає денормальне число, то це просто нуль, і проблем не повинно бути. Тому просто порядок порівняння повинен бути стійким проти цього.