浮點數在計算機中的表示
阿新 • • 發佈:2020-12-25
接上一篇部落格《為什麼會有補碼?》,我僅僅分析了整數在計算機中表示方式,但是計算機中的浮點數又是如何表示的呢?
引子
首先,使用之前部落格的程式,可以看到如下的這些實數在計算機中的計算結果是
實際數值 | 數值型別 | 計算機中的表示 |
---|---|---|
102.3235 | float | 42CCA5A2 |
-3.256 | float | C050624E |
120.254 | double | 405E104189374BC7 |
-56.2441 | double | C04C1F3EAB367A10 |
右邊的計算機中的數值表示是按照《IEEE 754-2008》的標準儲存資料的,具體的規定如下所示。
IEEE 754 標準
表示形式
IEEE 754 規定了二進位制浮點數在計算中的儲存方式,我們以 C 語言中的 float 為例來具體說明。無論是 32 位系統還是 64 位系統,計算機中的 float 佔用 4 個位元組,我們就使用這些位元組來儲存任意的浮點數,可以參考下圖
轉化成對應的數學表示形式,浮點數 VV
\[V = (-1)^s\times M\times 2^E \]- ss 表示符號位,佔據 1 個 bit 位,如果是負數則 s=1s=1,如果是非負數則 s=0s=0;
- MM 表示 mantissa,佔據 23 個位元,表示有效數字,表示的數字介於 1 和 2 之間;
- EE 為非負整數,表示基於 2 為基數的指數大小,佔據 8 個位元。
因此,如果確認了上面 3 個引數,也就唯一確定了浮點數在計算機中的儲存形式。我們以102.3235
為例,來看看上面的這幾個數字是如何表示出來的?
102.3235
的二進位制原碼形式是1100110.01010010110100001110 = 1.10011001010010110100001110*2^6
- 確認 ss。因為是正數,因此 s=0s=0。
- 確認 MM。MM 表示
1.xxxxxx
之後的xxxxxx
的部分,即計算機內部儲存 MM 時,預設表示的第一位總是 1,可以捨棄表示 1 的這一位,而僅僅儲存小數點之後的部分。因此 M=10011001010010110100001110M=10011001010010110100001110,因為只能儲存 23 個位元,將多餘的位數部分截斷得到 M=10011001010010110100001M=10011001010010110100001。 - 確認 EE。它是個肺腑正數,按照第 1 步計算出來的結果,我們的指數應該是 6。但是,IEEE 規定根據二進位制計算浮點數時,需要給指數減去一個偏置值,對於 float 型別這個數為 127,對於 double 型別,這個數是 1023。因此反過來,在將數字轉換成二進位制儲存的時候,要加上這個偏置值,因此 E=6+127=133E=6+127=133。
- 綜合以上的所有計算結果,最後在計算機中儲存的形式是
01000010110011001010010110100001
,轉換成 16 進位制就是42CCA5A2
。
特別規定
依照上面的方法,可以依次確認其他 3 個浮點數的表示形式。這都是比較常規的規格化資料的處理方法,IEEE 針對一些特殊的數字(絕對值特別接近 0 的數字或者無窮大無窮小),引入了一些特殊的規定,稱為非規格化表示方法,總結如下。
- 規格化資料。如果指數部分既不是 0 也不是 255(EE 不全為 0 或者不全為 1),就是規格化儲存方式,具體的計算方法與之前介紹的相同。
- 非規格化資料。EE 全為 0 就是非規格化的資料,此時的指數固定為 1-127 或者 1-1023,有效數字 MM 的計算不再捨棄第一位的 1,而是 0.xxxxxxxx 的小數部分,這樣就可以表示 0 和非常接近 0 的小數字。需要注意的是,0 有兩種表示。
- 特殊數字。EE 全為 1 表示特殊的數字
- 如果 MM 全為 0,表示無窮大,正負取決於符號 ss;
- 如果 MM 不全為 0,表示這是一個非數 NaN(Not a Number)。
精度誤差及表示範圍
如果明白之前的內容,那就可以計算出來每種表示方法的取值範圍以及表示的資料誤差。在計算之前,有如下的一些假設:
- 正數和負數的表示方法是對稱的,因此我們僅僅關注正數即可;
- 不考慮特殊值的計算,因為其僅僅是計算了不同幾個數值,沒有計算的價值。
如果需要計算最大的規格化數字,那麼其在記憶體中的表示應該是 s=1,M=1.11…1,E=111…10s=1,M=1.11…1,E=111…10,最後的結果就是 1.1111…1×2127=3.4×10381.1111…1×2127=3.4×1038,其他的基本可以推測出來了,如下表所示