I have a numerical function f(x, y) returning a double floating point number that implements some formula and I want to check that it is correct against analytic expressions for all combination of the parameters x and y that I am interested in. What is the proper way to compare the computed and analytical floating point numbers?
Let's say the two numbers are a and b. So far I've been making sure that both absolute (abs(a-b) < eps) as well as relative (abs(a-b)/max(abs(a), abs(b)) < eps) errors are less than eps. That way it will catch numerical inaccuracies even if the numbers are let's say around 1e-20.
However, today I discovered a problem, the numerical value a and analytic value b were:
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
So the absolute error [50] is (obviously) small, but the relative error [52] is large. So I thought that I have a bug in my program. By debugging, I realized, that these numbers are denormal. As such, I wrote the following routine to do the proper relative comparison:
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
Where tiny(1._dp) returns 2.22507385850720138E-308 on my computer. Now everything works and I simply get 0 as the relative error and all is ok.
In particular, the above relative error [52] is wrong, it's simply caused by insufficient accuracy of the denormal numbers. Is my implementation of the rel_error function correct? Should I just check that abs(a-b) is less than tiny (=denormal), and return 0? Or should I check some other combination, like
max(abs(a), abs(b))?
I would just like to know what the "proper" way is.
exp(log_gamma(m+0.5_dp) - (m+0.5_dp)*log(t)) / 2for m=234, t=2000. It goes to zero quickly as I increasem. All I want to make sure that my numerical routine returns "correct" numbers (to return zero is perfectly fine too) to at least 12 significant digits. So if the calculation returns a denormal number, then it's simply zero, and there should be no problem. So just the comparison routine needs to be robust against this. – Ondřej Čertík Sep 24 '12 at 04:55