將一個十進位數轉換成 IEEE 754 浮點數格式,意思是將該值表示為 1 位元的正負號、一個帶偏差的指數欄位,以及一個分數欄位,全部封裝成固定寬度 32 位元或 64 位元的字。32 位元的形式稱為 binary32(單精度),而 64 位元的形式稱為 binary64(雙精度)。這兩種佈局皆遵循 IEEE 754 標準中的二進位浮點數算術規範,也是所有現代 CPU、GPU 和網頁瀏覽器用於 float 與 double 數值的格式。此轉換是完全確定性的:對於你輸入的任何十進位數值,在你選擇的格式中恰好存在唯一一個 IEEE 754 位元樣式,且該樣式可以被解碼回瀏覽器實際將儲存的同一數值。若想在不手寫剖析程式的情況下檢視該樣式,可以使用 IEEE 754 浮點數轉換器,它能透過瀏覽器的 DataView API,將十進位數編碼為 binary32 或 binary64 的欄位,並將位元或十六進位表示法解碼回瀏覽器的數值。每一個步驟皆在本地端執行,因此瀏覽器將為你的數值保存的確切位元組是可見的,無須經過近似處理。

convert decimal number into ieee 754 floating point format
convert decimal number into ieee 754 floating point format

binary32 與 binary64 的 IEEE 754 位元佈局

每一個 IEEE 754 二進位浮點數值,無論是單精度或雙精度,皆由相同的三個部分構成:單一的正負號位元、帶有固定偏差的指數欄位,以及儲存小數點後位元的分數欄位(也稱為尾數或有效數)。兩種格式的寬度不同,但佈局的文法是相同的,這也是為何同一套轉換邏輯能同時處理兩者的原因。

欄位Binary32(單精度)Binary64(雙精度)
總位元數3264
正負號位元11
指數位元811
分數位元2352
指數偏差1271023
指數範圍(無偏差,標準數)-126 至 +127-1022 至 +1023
最小正非正規數2^-1492^-1074
交換形式的十六進位位數816

指數以帶偏差的方式儲存,這意味著實際指數加上偏差就是位元中所呈現的值。對於一個標準數來說,無偏差指數等於儲存指數減去偏差(binary32 為 127,binary64 為 1023)。對於非正規數而言,無偏差指數為偏差減一,因此公式會平移一個單位。正負號位元在非負值為 0,在負值為 1;正零與負零的指數欄位皆為全零,分數欄位也皆為全零,僅正負號位元在兩者間翻轉。這些格式的十六進位輸出以最高有效位元組優先顯示,且 binary32 恰好使用八個十六進位位數,binary64 則使用十六個,當你將其複製到其他工具或檔案中使用時不會加上 0x 前綴。

為何 binary32 會改變你的十進位數值

當你在轉換器中輸入像 0.1 或 1234567 這樣的十進位數並選擇 binary32 時,結果極少是你所輸入的精確十進位數,而這種不符並非錯誤。JavaScript 首先會將該十進位數剖析為一個雙精度 Number,接著 DataView 將那個雙精度數四捨五入到最接近的可表示 binary32 值。你在輸出中看到的「儲存值」是四捨五入後的單精度結果,而非原始的十進位拼寫。對於 binary64 而言,儲存值反映的是瀏覽器的雙精度交換值,而非原始的十進位拼寫,因此像 0.1 這樣的數值在套用該最接近的可表示四捨五入後,仍然與輸入內容不同。

這代表轉換為 IEEE 754 永遠是從你的十進位數投影到所選格式中最接近的可表示二進位浮點數值。IEEE 754 浮點數轉換器透過以大端位元組順序呼叫 DataView.getFloat32 或 DataView.getFloat64 來讀回位元樣式來呈現這點,因此你所看到的位元正是瀏覽器將儲存的位元,而非該工具手動計算出的近似值。當你需要保留精確的十進位拼寫時,請改用十進位或任意精度函式庫:IEEE 754 無法精確表示大部分十進位分數,因為其二進位展開是無窮的。請將轉換器回報的儲存值視為實際的數值量,而非你所輸入的十進位數。

將十進位數轉換為 IEEE 754 格式

轉換器的核心圍繞著兩個相反方向:十進位到位元,以及位元或十六進位到十進位。「十進位到位元」是大多數讀者來使用的路徑,以下步驟將帶你走過該流程以及結果中該注意的內容。

  1. 開啟 IEEE 754 浮點數轉換器並選擇「十進位到位元」方向,接著從格式選擇器中挑選 binary32(單精度)或 binary64(雙精度)。
  2. 以一般十進位表示法輸入單一十進位數值,可選擇性地包含正負號、小數部分與十進位指數。輸入也接受特殊符號 Infinity、-Infinity 與 NaN。將欄位留空以清除內容:空白的輸入會被拒絕,而不會被視為零。
  3. 點擊轉換。該工具會以大端位元組順序透過 DataView.setFloat32 或 DataView.setFloat64 寫入你的數值,接著讀回儲存的數值並呈現完整的分解結果。
  4. 檢視正負號、指數、分數、分類、儲存值,以及依標準欄位寬度切分(binary32 為 1 + 8 + 23,binary64 為 1 + 11 + 52)的二進位位元字串。
  5. 複製十六進位交換形式(binary32 為八個十六進位位數,binary64 為十六個,無 0x 前綴),並對照將使用它的通訊協定、檔案格式或硬體所預期的位元組順序與精度進行驗證。

十六進位數值字面量、以逗號分隔的數字、單位,以及特定區域的十進位分隔符號會在輸入時被拒絕。這種明確的拒絕很重要,因為它能防止 JavaScript 隱性的型別轉換將剖析錯誤隱藏在看似合理的位元樣式之後。例如,輸入的「1,000」不會悄悄變成一千;它會被拒絕,以便你能將其更正為「1000」或「1.0e3」後再試一次。

在轉換後讀取已解碼的欄位

完成一次轉換後,有四個欄位能提供最多關於位元實際意義的訊息。正負號為單一的 0 或 1。指數是直接從位元樣式取出的原始帶偏差值;若為標準 binary32 值則減去 127,若為標準 binary64 值則減去 1023 以取得無偏差指數,若為非正規數則使用偏差減一。分數欄位是附加隱含前導 1 之後的原始位元,因此對於標準數而言,有效數在二進位中為 1.fraction。分類行會告訴你指數與分數樣式落在哪一個類別。

作為一個可驗證的參考,binary32 中的十進位數值 1.0 可分解為:正負號 0、帶偏差指數 127(二進位 01111111)、分數 0、分類為標準數、儲存值 1,以及十六進位 3F800000。位元字串 0 01111111 00000000000000000000000 讀作「正值,指數欄位為 127,未設定任何分數位元」,這就是 1 的標準單精度編碼。同一個數值在 binary64 中為:正負號 0、帶偏差指數 1023、分數 0、儲存值 1,以及十六進位 3FF0000000000000。這些是轉換器測試集中的參考樣例,因此在信任該工具處理更刁鑽的輸入之前,它們是確認工具運作正確的良好數值。

IEEE 754 精度何時重要、何時不重要

即使在工具完美運作的情況下,有兩種情況會讓十進位到 IEEE 754 的轉換產生誤差。第一種是其二進位展開為無窮的十進位分數:0.1、0.2、0.3,以及幾乎所有不是 2 的冪次和的數值,皆會四捨五入到最接近的可表示二進位值。轉換器回報的是該四捨五入後的儲存值,而非原始的十進位數,而這正是你在與瀏覽器實際行為比較時所需要的資訊。第二種情況是大型整數:binary64 僅能精確表示到 2^53 以下的整數,而 binary32 則更早放棄,約在 2^24 左右,因為僅有 24 位元的有效數可供使用。

指數樣式分數樣式分類
全零全零零(正負號決定 +0 或 -0)
全零非零非正規數
全一全零無窮大(正負號決定 +∞ 或 -∞)
全一非零NaN
其他任何樣式任何標準數

對於金錢、識別碼、必須能精確往返的計數器,或任何一個丟失的最小單位都會造成影響的領域,請勿依賴 IEEE 754:請使用十進位函式庫或整數表示法。對於繪圖、訊號處理、科學模擬,以及早已規定必須使用 IEEE 754 的通訊協定標頭,轉換器正是用來驗證你即將送出的位元組與接收端所預期內容一致 的正確工具。進位制轉換的配套指南涵蓋了反向的情境,亦即你從位元出發並想在另一個進位制中讀取它們,而 IEEE 754-2019 標準則是此處所使用之所有欄位寬度、偏差與分類規則的權威來源。