0

เครื่องมือแสดงภาพ IEEE-754 Float

ดูว่าเลขทศนิยมถูกจัดเก็บในรูปแบบ IEEE-754 float อย่างไร — บิตเครื่องหมาย, บิตเลขชี้กำลัง และบิตแมนทิสซา — และทำไมเลขอย่าง 0.1 ถึงไม่ถูกเก็บอย่างแม่นยำ

🔒 ประมวลผลทั้งหมดในเบราว์เซอร์ของคุณ — ไม่มีการอัปโหลดสิ่งใดที่คุณป้อนที่นี่

กำลังประมวลผล... 0%
กำลังทำนอร์มัลไลซ์
กำลังคำนวณค่าไบแอสของเลขชี้กำลัง
กำลังขยายบิตแมนทิสซา
เสร็จ

ผลลัพธ์

เลขทศนิยมทุกตัวที่คอมพิวเตอร์เก็บ — ตัวเลขใน JavaScript, float ในภาษา C, float ใน Python — ถูกเข้ารหัสในรูปแบบเดียวกันภายใต้มาตรฐาน IEEE 754: หนึ่งบิตเครื่องหมาย, กลุ่มบิตเลขชี้กำลัง และกลุ่มบิตแมนทิสซา (เศษส่วน) ความละเอียด 32 บิต (single) ใช้ 1 บิตเครื่องหมาย, 8 บิตเลขชี้กำลัง และ 23 บิตแมนทิสซา ส่วนความละเอียด 64 บิต (double) ซึ่งเป็นรูปแบบพื้นฐานของชนิดตัวเลขในเกือบทุกภาษา ใช้ 1 บิตเครื่องหมาย, 11 บิตเลขชี้กำลัง และ 52 บิตแมนทิสซา เครื่องมือนี้รับเลขทศนิยมที่คุณพิมพ์ เข้ารหัสในความกว้างใดความกว้างหนึ่งโดยใช้ตัวเข้ารหัส DataView/ArrayBuffer ในเบราว์เซอร์ — กลไกเดียวกับที่โค้ดของคุณทำงานอยู่จริง — แล้วระบายสีแต่ละบิตตามบริเวณที่บิตนั้นอยู่

การเข้ารหัสนั้นมีสามขั้นตอน และเครื่องมือนี้จะเดินผ่านทุกขั้นตอนแทนที่จะแสดงแค่บิตสุดท้าย ขั้นแรก การทำนอร์มัลไลซ์: ตัวเลขถูกเขียนใหม่เป็น 1.แมนทิสซา × 2^เลขชี้กำลัง โดยมีเลขที่ไม่ใช่ศูนย์เพียงหนึ่งหลักก่อนจุดทศนิยมฐานสอง (ตัวเลขที่เล็กเกินไปสำหรับรูปแบบนั้นจะถูกจัดการแบบซับนอร์มัล โดยไม่มีเลข 1 นำหน้าโดยปริยาย) ขั้นที่สอง ค่าไบแอสของเลขชี้กำลัง: เนื่องจากฟิลด์เลขชี้กำลังต้องเก็บทั้งเลขชี้กำลังบวกและลบในรูปแบบจำนวนไม่มีเครื่องหมาย จึงต้องบวกค่าไบแอสคงที่ (127 สำหรับความละเอียด 32 บิต, 1023 สำหรับ 64 บิต) ก่อนที่จะเขียนฟิลด์นี้เป็นเลขฐานสอง ขั้นที่สาม แมนทิสซาส่วนเศษส่วนถูกขยายทีละบิตด้วยวิธีการดั้งเดิม “คูณด้วยสอง, นำส่วนจำนวนเต็มเป็นบิตถัดไป, เก็บส่วนที่เหลือ” — ทำซ้ำจนเต็มฟิลด์แมนทิสซา หลังจากนั้นบิตที่เหลือจะเป็นตัวตัดสินว่าผลลัพธ์จะถูกปัดขึ้นหรือลง (ปัดครึ่งไปยังค่าเลขคู่ ซึ่งเป็นค่าเริ่มต้นของ IEEE-754)

นี่คือเหตุผลว่าทำไมเลขธรรมดาอย่าง 0.1 จึงไม่ถูกเก็บอย่างแม่นยำ ในเลขฐานสอง 0.1 เป็นเศษส่วนซ้ำ (0.0001100110011… ไม่รู้จบ) ดังนั้นแมนทิสซาที่มีความยาวจำกัดจึงเก็บมันไม่ได้แบบแม่นยำ — มันต้องถูกปัดเศษที่จุดใดจุดหนึ่ง ลองเข้ารหัส 0.1 เป็น float 32 บิต แล้วอ่านค่าบิตกลับมา คุณจะไม่ได้ 0.1 กลับมา: คุณจะได้ 0.100000001490116119384765625 พอดี ความละเอียด 64 บิตมีบิตแมนทิสซาเพิ่มขึ้นอีก 29 บิต ดังนั้นค่าผิดพลาดจากการปัดเศษจึงน้อยกว่ามาก แต่มันก็ไม่ใช่ศูนย์ — 0.1 ในรูปแบบ double 64 บิตคือ 0.1000000000000000055511151231257827021181583404541015625 พอดี เครื่องมือนี้คำนวณค่าที่เก็บแน่นอนนั้นด้วยเลขคณิตจำนวนเต็มขนาดใหญ่ (ไม่ใช้ทางลัดของเลขทศนิยม) ดังนั้นช่องว่างระหว่างสิ่งที่คุณพิมพ์กับสิ่งที่ฮาร์ดแวร์เก็บจริงจะไม่มีวันถูกซ่อนหรือประมาณค่า

ค่าพิเศษต่างๆ มีรูปแบบบิตที่สงวนไว้แน่นอน แทนที่จะใช้การเข้ารหัสปกติ: ศูนย์และลบศูนย์มีบิตเลขชี้กำลังและแมนทิสซาเป็นศูนย์ทั้งหมด (ต่างกันเพียงบิตเครื่องหมาย), ±อนันต์ มีบิตเลขชี้กำลังเป็นหนึ่งทั้งหมดพร้อมกับแมนทิสซาเป็นศูนย์ทั้งหมด, และ NaN มีบิตเลขชี้กำลังเป็นหนึ่งทั้งหมดพร้อมกับบิตแมนทิสซาอย่างน้อยหนึ่งบิตที่ถูกเซ็ต ทุกอย่างที่นี่ทำงานในเบราว์เซอร์ของคุณเท่านั้น — ไม่มีสิ่งใดที่คุณพิมพ์ถูกอัปโหลดไปที่ใด — ซึ่งทำให้ที่นี่เป็นที่ที่ปลอดภัยในการสร้างสัญชาตญาณที่แท้จริงเกี่ยวกับบั๊กของเลขทศนิยม: ทำไม `0.1 + 0.2 !== 0.3` ในเกือบทุกภาษาโปรแกรม, ทำไมเท็กซ์เจอร์ float32 ในโค้ดกราฟิกจึงสูญเสียความละเอียดที่ float64 ไม่เป็น, และทำไมโค้ดทางการเงินโดยทั่วไปควรหลีกเลี่ยงเลขทศนิยมฐานสองไปเลย