나는 수치 기능이 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입니다. 내가 증가함에 따라 그것은 빨리 0으로 간다m
. 숫자 루틴이 "올바른"숫자 (0을 반환하는 것도 괜찮음)를 12 자리 이상의 유효 숫자로 반환하도록하고 싶습니다. 따라서 계산에서 비정규 숫자를 반환하면 단순히 0이며 문제가 없습니다. 따라서 비교 루틴 만 강력하게해야합니다.