ฉันมีฟังก์ชั่นเชิงตัวเลข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] นั้นใหญ่ ดังนั้นฉันคิดว่าฉันมีข้อบกพร่องในโปรแกรมของฉัน โดยการแก้จุดบกพร่องฉันตระหนักว่าตัวเลขเหล่านี้จะdenormal ดังนั้นฉันจึงเขียนขั้นตอนต่อไปนี้เพื่อทำการเปรียบเทียบที่เหมาะสม:
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)
น้อยกว่าจิ๋ว (= denormal) และส่งคืน 0 หรือไม่ หรือฉันควรตรวจสอบชุดค่าผสมอื่น ๆ เช่น
max(abs(a), abs(b))
?
ฉันแค่อยากจะรู้ว่าสิ่งที่ "เหมาะสม" คืออะไร
exp(log_gamma(m+0.5_dp) - (m+0.5_dp)*log(t)) / 2
สำหรับ m = 234, t = 2000m
มันจะไปให้เป็นศูนย์ได้อย่างรวดเร็วที่สุดเท่าที่ฉันเพิ่มขึ้น ทั้งหมดที่ฉันต้องการเพื่อให้แน่ใจว่าตัวเลขประจำของฉันส่งกลับตัวเลข "ถูกต้อง" (เพื่อกลับศูนย์ก็ดีเหมือนกัน) เป็นอย่างน้อย 12 หลักที่สำคัญ ดังนั้นหากการคำนวณส่งกลับตัวเลข denormal แล้วมันก็เป็นศูนย์และไม่น่ามีปัญหา ดังนั้นเพียงแค่การเปรียบเทียบประจำจะต้องแข็งแกร่งต่อนี้