我有一个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。现在一切正常,相对误差为零,一切正常。特别是,上述相对误差[52]是错误的,这仅是由于非正规数的准确性不足引起的。我对rel_error
函数的实现正确吗?我是否应该检查一下这个值abs(a-b)
是否小于small(= normal),然后返回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个有效数字。因此,如果计算返回的是非正规数,则它只是零,因此应该没有问题。因此,仅比较例程需要对此具有鲁棒性。