Tôi có một hàm số f(x, y)
trả về một số dấu phẩy động kép thực hiện một số công thức và tôi muốn kiểm tra xem nó có đúng với các biểu thức phân tích cho tất cả sự kết hợp của các tham số x
và y
tôi quan tâm không. Cách nào là đúng để so sánh tính toán và phân tích số dấu phẩy động?
Hãy nói hai số là a
và b
. Cho đến nay tôi đã chắc chắn rằng cả lỗi tuyệt đối ( abs(a-b) < eps
) cũng như tương đối ( abs(a-b)/max(abs(a), abs(b)) < eps
) đều nhỏ hơn eps. Bằng cách đó, nó sẽ bắt được những điểm không chính xác về số ngay cả khi các con số được cho là khoảng 1e-20.
Tuy nhiên, hôm nay tôi phát hiện ra một vấn đề, giá trị số a
và giá trị phân tích b
là:
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
Vì vậy, lỗi tuyệt đối [50] là (rõ ràng) nhỏ, nhưng lỗi tương đối [52] là lớn. Vì vậy, tôi nghĩ rằng tôi có một lỗi trong chương trình của tôi. Bằng cách gỡ rối, tôi nhận ra, đó là những con số này denormal . Như vậy, tôi đã viết các thói quen sau đây để làm so sánh tương đối thích hợp:
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
Trường hợp tiny(1._dp)
trả về 2.22507385850720138E-308 trên máy tính của tôi. Bây giờ mọi thứ hoạt động và tôi chỉ đơn giản nhận được 0 là lỗi tương đối và tất cả đều ổn. Cụ thể, lỗi tương đối ở trên [52] là sai, nó đơn giản là do không đủ độ chính xác của các số bất thường. Là tôi thực hiện các rel_error
chức năng chính xác? Tôi có nên kiểm tra nó abs(a-b)
nhỏ hơn nhỏ (= không bình thường) và trả về 0 không? Hoặc tôi nên kiểm tra một số kết hợp khác, như thế
max(abs(a), abs(b))
nào?
Tôi chỉ muốn biết cách "thích hợp" là gì.
exp(log_gamma(m+0.5_dp) - (m+0.5_dp)*log(t)) / 2
cho m = 234, t = 2000. Nó đi về không nhanh chóng khi tôi tăng lênm
. Tất cả tôi muốn đảm bảo rằng thói quen số của tôi trả về các số "chính xác" (để trả về số 0 cũng hoàn toàn tốt) với ít nhất 12 chữ số có nghĩa. Vì vậy, nếu phép tính trả về một số bất thường, thì nó chỉ đơn giản là 0 và sẽ không có vấn đề gì. Vì vậy, chỉ cần các thói quen so sánh cần phải mạnh mẽ để chống lại điều này.