บทความทั้งหมด

IEEE 754: เหตุใด 0.1 + 0.2 จึงไม่เท่ากับ 0.3 ในโค้ด

เปิด console ของ JavaScript ในเบราว์เซอร์แล้วพิมพ์ 0.1 + 0.2 — แทนที่จะได้ 0.3 กลับได้ 0.30000000000000004 นี่ไม่ใช่บั๊กของ JavaScript โดยเฉพาะ แต่เป็นผลโดยตรงจากวิธีที่มาตรฐาน IEEE 754 แทนค่าตัวเลขทศนิยมในระบบฐานสอง และผลลัพธ์แบบเดียวกันนี้ก็เกิดขึ้นใน PHP, Java, Python และแทบทุกภาษาที่ใช้มาตรฐานนี้

สามส่วนของตัวเลขทศนิยม

ตัวเลขตาม IEEE 754 ถูกเก็บเป็นสามส่วนประกอบ: เครื่องหมาย (บวกหรือลบ) แมนทิสซา (หลักที่มีนัยสำคัญของตัวเลข) และเลขชี้กำลัง (กำลังที่จุดทศนิยมถูกเลื่อน) คล้ายกับสัญกรณ์วิทยาศาสตร์: 1.5 × 10² เพียงแต่เป็นระบบฐานสอง

เหตุใด 0.1 จึงไม่สามารถแทนค่าได้แม่นยำในระบบฐานสอง

0.1 ในระบบฐานสิบเป็นเศษส่วนไม่สิ้นสุดในระบบฐานสอง (คล้ายกับที่ 1/3 ไม่สิ้นสุดในระบบฐานสิบ) คอมพิวเตอร์เก็บบิตแมนทิสซาได้จำนวนจำกัดเท่านั้น ดังนั้นตัวเลขจึงถูกปัดเศษเป็นค่าที่ใกล้เคียงที่สุดที่แทนค่าได้ — และการปัดเศษนี้เองที่ก่อให้เกิด "ข้อผิดพลาด" ที่มองเห็นได้

จุดที่สร้างปัญหาจริง: ยอดรวมตะกร้าสินค้า

หน้าชำระเงินที่บวกราคาสินค้าแต่ละชิ้นเป็น float ธรรมดาอาจได้ยอดรวมคลาดเคลื่อนไปสองสามสตางค์จากที่ควรจะเป็น หลังจากบวกสินค้าหลายรายการ — การบวกแต่ละครั้งปัดเศษเล็กน้อย และข้อผิดพลาดสะสมแทนที่จะหักล้างกัน นี่คือเหตุผลที่ระบบชำระเงินมักคำนวณเป็นสตางค์แบบจำนวนเต็ม หรือใช้ type decimal เฉพาะทาง แทนที่จะบวก float ตรง ๆ

ทำไมต้องใช้สิ่งนี้

  • เข้าใจและวินิจฉัยข้อผิดพลาดจากการปัดเศษที่ไม่คาดคิดในการคำนวณทางการเงินหรือวิทยาศาสตร์
  • ดูการแทนค่าฐานสองที่แม่นยำของตัวเลขทศนิยมที่ระบุ
  • อธิบายให้เพื่อนร่วมงานหรือนักเรียนฟังว่าเหตุใดการเปรียบเทียบตัวเลขทศนิยมด้วยความเท่ากันแบบแน่นอนจึงเป็นวิธีปฏิบัติที่ไม่ดี

เลขซับนอร์มัลใกล้ศูนย์

เมื่อค่าของตัวเลขมีขนาดเล็กเกินไปสำหรับการแสดงผลปกติ (แมนทิสซาที่เริ่มต้นด้วยเลข 1 โดยนัย) IEEE 754 จะเปลี่ยนไปใช้โหมดซับนอร์มัล (denormalized) ซึ่งเลข 1 โดยนัยนี้จะถูกละทิ้ง — สิ่งนี้ช่วยให้แสดงตัวเลขที่มีขนาดเล็กลงไปอีกได้ โดยแลกกับการสูญเสียความละเอียดอย่างค่อยเป็นค่อยไปแทนที่จะกระโดดไปที่ศูนย์ทันที การเปลี่ยนผ่านไปสู่ศูนย์อย่าง "นุ่มนวล" นี้ดีกว่าการเป็นศูนย์ทันที แต่การคำนวณแบบซับนอร์มัลจะช้ากว่าการคำนวณปกติอย่างเห็นได้ชัดในโปรเซสเซอร์บางรุ่น

ลองใช้เครื่องมือ