f(x, y)
いくつかの数式を実装する二重浮動小数点数を返す数値関数があり、パラメーターのすべての組み合わせの分析式に対して正しいことx
とy
、興味があることを確認したいと思います。計算された値と分析浮動小数点数?
2つの数値が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)
がtiny(=非正規)未満であることを確認し、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桁の有効数字(ゼロを返すことも完全に適切です)を返すことを確認したいすべてです。したがって、計算が非正規数を返す場合、それは単にゼロであり、問題はないはずです。したがって、比較ルーチンだけがこれに対して堅牢である必要があります。