IEEE 754 轉換工具|浮點數⇔位模式互轉(32/64位)

十進位制小數與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)。可以在上方的轉換工具中親自輸入這些數值,比較末位的差異。

什麼是IEEE 754?用位模式看浮點數

電腦在儲存一個十進位制小數時,並不會原樣保留你輸入的數字,而是按照IEEE 754標準,把這個值拆分成符號、指數部、尾數部三部分,裝進固定長度的位元(bit)中。這個工具可以讓你直接看到,任意輸入值在單精度(32位)和雙精度(64位)下分別被存成了怎樣的位模式,也支援反向操作:貼上一段十六進位制或二進位制位模式,就能知道它對應的十進位制數值。

日常程式設計中很少需要關心這一層,但`0.1 + 0.2`為什麼不等於`0.3`、超大整數存成浮點數後為什麼會遺失精度、NaN與無窮大在比較運算中為何表現特殊,答案都藏在這套位結構裡。把符號位、指數部、尾數部拆開擺在一個真實數值上,抽象的規則就變得可以直接指認了。

使用方法

  1. 選擇轉換方向與精度 選擇「十進位制 → 位模式」或「位模式 → 十進位制」,再指定單精度(32位)或雙精度(64位)。
  2. 輸入數值 十進位制輸入除一般數字外,還可輸入「NaN」・「Infinity」・「-Infinity」。位模式輸入需使用`0x`開頭的十六進位制,或位數與所選精度一致的二進位制。
  3. 查看符號・指數部・尾數部的拆解 透過分色顯示的位元串與詳情表,確認原始指數值、去除偏移後的實際指數值以及完整的十六進位制表示。
  4. 閱讀分類標籤與說明 結果會被自動判定為零・非規格化數・規格化數・無窮大・NaN之一,並附有簡要說明。
  5. 嘗試預設按鈕與邊界情形 點選0.1・0.2・0.3、±0、±Infinity、NaN的預設按鈕,或輸入負數及極大/極小的數值,比較它們的編碼結果。

用好本工具的小技巧

  • 將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`字首可省略)。

適用場景

電腦科學課程學習

教科書上抽象描述的浮點數內部結構,可以用真實數值直接驗證,適合複習或撰寫實驗報告時使用。

排查數值精度相關的程式錯誤

不用寫程式碼,只需輸入可疑數值查看其精確位模式,就能縮小「為什麼偏偏這個計算出現誤差」的原因範圍。

嵌入式與底層程式設計

把記憶體傾印或暫存器中看到的十六進位制浮點數值,反向解碼成易讀的十進位制數值。

技術面試與筆試準備

針對「單精度與雙精度在位元級別上有何區別」這類常見問題,用具體例子而非死記硬背來準備答案。

向他人解釋「0.1 + 0.2 ≠ 0.3」

不必只靠口頭斷言捨入誤差,直接展示實際的位模式對比,讓對方一眼看懂。

術語表

IEEE 754
規定電腦如何表示浮點數的國際標準。1985年發布,幾乎所有程式語言的float/double型別都遵循這一規格。
符號位
表示數值正負的1個位元。0為正、1為負,獨立於指數部與尾數部之外,因此「+0」與「-0」作為不同的位模式而存在。
指數部
表示數值量級(大小規模)的位元串,單精度為8位、雙精度為11位,以加上偏移量後的形式儲存。
尾數部
表示數值有效數字(精度)的位元串,單精度為23位、雙精度為52位,通常按開頭帶有隱含1的方式解讀。
偏移量(bias)
為了讓指數部能以無符號整數形式儲存和比較而加上的固定值,單精度為127、雙精度為1023。
非規格化數
指數部全為0且尾數部不為0的位模式。省略尾數部開頭的隱含1,以犧牲精度為代價表示比通常最小值更接近零的數值。
NaN(非數)
指數部全為1且尾數部不為0的位模式,由0/0、∞-∞等數學上未定義的運算產生。
無窮大
指數部全為1且尾數部全為0的位模式,通常在計算結果超出可表示範圍(溢位)時出現。

常見問題

0.1、0.2、0.3在二進位制中都是無限迴圈小數,計算機必須將它們四捨五入以適應有限位數的尾數部(雙精度為52位)。由於0.1與0.2各自的舍入誤差方向恰好沒有相互抵消,兩者相加的結果與0.3的精確位模式略有不同(結果為0.30000000000000004)。這並非某個特定程式語言的缺陷,而是所有遵循IEEE 754標準的語言共有的現象。

單精度(float,32位)由1位符號位、8位指數部、23位尾數部組成;雙精度(double,64位)由1位符號位、11位指數部、52位尾數部組成。尾數部位數越多,有效數字(精度)越高;指數部位數越多,可表示的數值範圍越廣。大多數程式語言的浮點數預設型別都是雙精度。

指的是指數部全為0但尾數部不為0的位模式。通常的(規格化的)浮點數在尾數開頭帶有隱含的1,而非規格化數省略了這一隱含1,轉而將指數固定為最小值,從而能夠表示比通常最小值更接近零的數值,但代價是犧牲了有效精度。

IEEE 754中符號位是獨立存在的一位,因此即便指數部與尾數部都全為0,符號位為0時得到"+0",為1時得到"-0",形成兩種不同的位模式。作為數值比較時0===-0成立,但在某些運算結果中會顯現差異,例如1/0得到+Infinity,而1/-0得到-Infinity。

兩者都通過指數部全為1的位模式表示。若尾數部全為0,則表示無窮大(通過符號位區分+Infinity與-Infinity);若尾數部不為0,則表示NaN(Not a Number,非數)。它們由0除法、∞-∞等數學上未定義的運算產生。
工具君

閒話 ― 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"這一疑問,無論在哪種程式語言中都會以相同的形式出現。