IEEE 754 浮點數位模式視覺化工具
將十進位制小數分解為IEEE 754單精度(32位)或雙精度(64位)的位模式並可視化展示,也可將位模式反向解碼為十進位制值。符號位、指數部、尾數部分色顯示,並支援識別NaN、無窮大與非規格化數。
經典案例:為什麼 0.1 + 0.2 不等於 0.3
在JavaScript中計算 `0.1 + 0.2` 得到的是 `0.30000000000000004`,而非 `0.3`。檢視雙精度的位模式即可理解原因。
| 數值 | 雙精度(64位)十六進位制 | 雙精度(64位)二進位制 |
|---|---|---|
| 0.1 | 0x3FB999999999999A | 0011111110111001100110011001100110011001100110011001100110011010 |
| 0.2 | 0x3FC999999999999A | 0011111111001001100110011001100110011001100110011001100110011010 |
| 0.3 | 0x3FD3333333333333 | 0011111111010011001100110011001100110011001100110011001100110011 |
| 0.1 + 0.2 | 0x3FD3333333333334 | 0011111111010011001100110011001100110011001100110011001100110100 |
0.1、0.2、0.3在二進位制中都是無限迴圈小數,無法完全放入52位的尾數部分,因此都會被四捨五入。由於0.1與0.2各自的舍入誤差方向恰好沒有抵消,兩者相加的結果與0.3的精確位模式相比只相差最後1位(0x3FD3333333333334)。可以在上方的轉換工具中親自輸入這些數值,比較末位的差異。
使用提示
- 將0.1、0.2、0.3分別以雙精度轉換為位模式,並與0.1+0.2的結果(0.30000000000000004)對比,可以直觀地發現只有最後1位不同。
- 在十進位制輸入框中輸入"-0",會得到只有符號位為1的位模式(與"+0"不同)。作為數值0===-0成立,但位表示本身是不同的。
- 當指數部全為0時,尾數部為0表示零,尾數部不為0則表示非規格化數——一種以犧牲精度為代價來表示極接近零的數值的特殊表示法。
- 將同一數值(如0.1)在單精度(32位)與雙精度(64位)之間切換,可以確認單精度的舍入誤差更大。
- 將位模式解碼為十進位制時,需要輸入以`0x`開頭的十六進位制字串,或位數與所選精度完全一致的二進位制字串(`0b`字首可省略)。
常見問題
閒話 ― IEEE 754如何成為一門"通用語言"
1985年以前,各計算機制造商都採用各自獨立的浮點數表示法。IBM、DEC、Cray等公司即便計算同一個"0.1",其舍入方式與可表示的數值範圍也會存在細微差異,導致在一臺機器上編寫的數值計算程式移植到另一臺機器時,結果往往會出現微小偏差。為了解決這一混亂局面,曾參與英特爾8087數值協處理器設計的加州大學伯克利分校學者William Kahan牽頭組織了跨行業的標準化工作,於1985年釋出了IEEE 754標準。
IEEE 754的核心思想,是將有限的位數(32位或64位)劃分為符號、指數部、尾數部三個部分的分工,以此近似表示無限多的實數。指數部負責數值的量級(大小規模),尾數部負責有效數字的精度,這樣即使位數有限,也能靈活覆蓋從極小到極大的數值範圍。指數部之所以要加上偏移量(單精度為127、雙精度為1023)後再儲存,是為了避免像有符號整數的補碼那樣複雜的符號處理,只需將位串作為普通整數直接比較即可判斷數值大小關係。
在二進位制中能夠被"精確"表示的小數,僅限於分母為2的冪的分數(如1/2、1/4、3/8等)。十進位制的0.1寫成分數是1/10,由於10不是2的冪,在二進位制中會變成0.0001100110011...這樣無限迴圈的小數。由於尾數部的位數有限,只能在某處截斷並四捨五入,這正是"計算機無法精確表示0.1"的根本原因。需要精確處理十進位制小數的會計系統之所以往往不使用浮點數,而改用整數運算或專門的十進位制型別(如BCD),原因也在於此。
IEEE 754此後在2008年、2019年經歷了修訂,新增了半精度(16位)、四倍精度(128位)以及十進位制浮點數等規定,但符號、指數部、尾數部三分結構以及舍入模式的核心思想,自1985年初版以來從未改變。由於幾乎所有程式語言的float/double型別都遵循這一標準,"為什麼0.1+0.2不等於0.3"這一疑問,無論在哪種程式語言中都會以相同的形式出現。