ขอสรุปวิธีแก้ปัญหาไว้ตรงนี้เผื่อคนขี้เกียจอ่านครับ
ถ่าจะทดสอบว่าค่าหนึ่งๆเป็น NaN รึเปล่าจะใช้ x == Double.NaN ไม่ได้ แต่สามารถใช้ Double.isNaN(x) ได้แทน (ภาษา Java)
ส่วนคำอธิบายขอก๊อปปี้จาก twitter ตัวเองมาแปะตามลำดับเวลาล่ะกัน (ขี้เกียจเรียบเรียงเช่นกัน :P)
- ที่ไม่เท่ากันเกิดจากคอมไพเลอร์ทำตามมาตรฐาน floating point IEEE 754 ที่บอกว่า NaN ไม่เท่ากับ NaN
- จริงๆแล้ว bit pattern ที่ represent ค่า NaN นั้นไม่ได้มีค่าเดียว แต่มีเป็น range เลย
- โดย Double.NaN จะไปเรียกเมธอด Double.longBitsToDouble(0x7ff8000000000000L) ซึ่ง 0x7ff8000000000000L เป็น bit pattern หนึ่งที่เป็นไปได้
- ซึ่งถ้าดูผิวเผินแล้วเหมือนว่า Double.NaN กับ Double.NaN ก็น่าจะได้ค่าเดียวกัน เพราะส่ง bit pattern เดียวกันเข้าไป
- (เสริม NaN มี 2 แบบถ้า bit ขึ้นต้นด้วย 0 คือ signaling NaN (sNaN)ถ้าขึ้นต้นด้วย 1 คือ quiet NaN (qNaN) ดังนั้น 0x7ff8000000000000L คือ sNaN)
- ซึ่งถ้า sNaN ถูกกระทำการทางคณิตศาสตร์แล้วค่าจะเปลี่ยนเป็น qNaN ซึ่งค่าไม่เท่าเดิม
- ในขณะที่บางโปรเซสเซอร์ เพียงแค่มีการ copy ค่า (ในระดับโปรเซสเซอร์) ก็จะทำการแปลงค่าทันที
- นอกจากแปลงประเภทแล้ว bit pattern ก็อาจเปลี่ยนไปใน range ของ NaN ที่มีอยู่
- ดังนั้นการเรียก Double.NaN หรือ Double.longBitsToDouble(0x7ff8000000000000L) ก็อาจจะได้ค่า NaN ในรูปแบบ double ที่มีbit patternไม่เหมือนเดิม
- ดังนั้นถ่าจะทดสอบว่าค่าหนึ่งๆเป็น NaN รึเปล่าจะใช้ x == Double.NaN ไม่ได้ แต่สามารถใช้ Double.isNaN(x) ได้แทน (ภาษา Java)
อ้างอิง
Javadoc
- http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Double.html#NaN
- http://download.oracle.com/javase/6/docs/api/java/lang/Double.html#longBitsToDouble(long)
IEEE 754 Standard
- http://en.wikipedia.org/wiki/IEEE_floating-point_standard
- http://en.wikipedia.org/wiki/NaN
- http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=4610935&con=yes&userType=inst
ไม่มีความคิดเห็น:
แสดงความคิดเห็น