計算機是如何表示浮點數的
相對于整數的表示,計算機對浮點數的表示稍顯麻煩,理解計算機是如何表示浮點數的對于編寫程序,尤其是對數據精度要求極高的程序十分有幫助。
20世紀80年代的時候各個計算機生成廠家都在努力的制定自己的浮點數表示規則,因此當時的浮點數表示并不統一,有的關注精度,有的關注表示的範圍,還有的更關注執行的速度和簡便性。直到1985年IEEE标準757的推出,這種情況才得以改變。
我們知道,十進制數dmdm-1··· d1d0 . d-1d-2···d-n的表示方法為每個十進制位di 乘以其對應位的權重然後再将其相加得到:
小數點左邊i=0時d0的權重為100=1,每向左看一位那麼相應權重需要乘以10,而小數點右邊每向右看一位相應位置權重要除以10. 因此 d-1的權重為10-1而d-n的權重為10-n。所以小數點左邊的權重是10的非負幂得到十進制小數的整數部分,而小數點右邊的權重是10的負幂得到小數部分。
二進制浮點數bmbm-1··· b1b0 . b-1b-2···b-n我套用十進制浮點數的表示方法,隻是權重不再乘以10的幂而是要用2的幂代替。
和十進制同樣的分析,小數點左邊i=0時b0的權重為20=1,每向左看一位那麼相應權重需要乘以2,而小數點右邊每向右看一位相應位置權重要除以2. 因此 b-1的權重為2-1而b-n的權重為2-n。所以小數點左邊的權重是2的非負幂得到二進制小數的整數部分,而小數點右邊的權重是2的負幂得到小數部分。
上面的表示方法稱為定點法。看似不錯,但是考慮計算機表示數據的位數有限,一般float類型的單精度數用4個字節(32個bit)來表示,而double型雙精度數用8個字節(64個bit)來表示。因此在上面的表示方法中精度十分有限。比如:十進制表示法無法準确表示1/3, 5/7這樣的數字。而二進制表示法隻能表示那些可以寫成 的數。其它值隻能近似表示,而且無法有效的表示範圍很大的浮點數。
IEEE中規定的浮點數表示方法有效解決了這個問題,下面給出其具體表示法:
IEEE中規定的浮點數表示方法用
來表示一個浮點數。下面具體說明:
- 上式中 (-1)s決定該浮點數的符号, s=1,該浮點數為負,s=0,該浮點數為正。
- M表示尾數(significand),二進制小數,它的範圍是[1, 2), 或者[0, 1)。注意由于精度問題,前面采用數學上的的左閉右開區間表示并不準确。這裡定義一個誤差量ɛ。那麼M的範圍可以表示為1 ~ 2-ɛ 或者 0 ~ 1-ɛ。實際上從M的英文表達更容易理解它的含義。
- E表示階碼(exponent),很明顯E是用來計算權重的。E可以是負數,權重的值為2E 。E的英文表達清楚的表明了其含義。
由于階碼E和尾數M的值需要進行處理才能得到,因此這裡将M和E分别看做m和e的函數。至此浮點數的三部分可以分為s, e, 和 m 三部分。因為符号位隻有兩個狀态0和1,因此用1位表示即可。對于m和e則需要用多個bit來表示。
對于單精度浮點數,e用8位表示,而m用23位表示。這樣 符号位數 e占用位數 m占用位數 = 1 8 23 = 32 位。在實際内存中符号位占據最高位(第31位),接下來8位(30 ~ 23位)用來表示e,剩下的23位(22 ~ 0位)用來表示m。參見下圖。
而對于雙精度浮點數來說,e用11位表示,m用52位表示。這樣 符号位數 e占用位數 m占用位數= 1 11 52 = 64 位。在實際内存中符号位占據最高位(第63位),接下來11位(62 ~ 52位)用來表示e,剩下的52位(51 ~ 0位)用來表示m。參見下圖。
浮點數在内存中的表示
由于單精度和雙精度在讨論中類似,下面針對單精度浮點數進行讨論。
由于e的值由8個bit表示, e的值計算機會按照無符号數解釋,所以其表示的範圍為[0, 255]。根據e的值,被編碼的值可以分為三種情況:
- e的值大于0 并且 小于255,這種數我們成為規範化的數。
- e的值等于0,這種數我們稱為非規範化的數。
- e的值等于255,這裡又分為兩種情況,第一種情況是尾數m=0,此時表示該數為無窮大。第二種情況是尾數m≠0,此時表示NaN(Not a Number)不是一個數。
上面三種情況(第3種情況又分為兩個子情況)可以參考下圖。可以看出階碼E決定一個數是規格化的,非規格化的還是特殊值。
浮點數的三種情況
下面對每種情況進行分析:
- 規格化的值
在這種情況下,e 的值 大于 0 并且小于255,這時階碼E會被計算機解釋為以偏置Biased形式表示的有符号數。因此階碼E=e-Bias, 這裡Bias為2(k-1) – 1(對于單精度k=8, 對于雙精度k=11), 由于這裡以單精度為例讨論,因此Bias = 27-1 = 127。根據E=e-Bias, 可得出階碼E的取值範圍為-126 ~ 127。
關于m部分,計算機會将其解釋為小數值。0.xxxxx, 因此 0 ≤ m < 1。計算機會将尾數M進行這樣的: M=1 m。因此M可以看做二進制小數 1.bnbn-1··· b1b0 的數字。
- 非規格化的值
當e = 0 時,所表示的數即為非規格化的數。這種情況下E = 1- Bias,而尾數M=m。
為什麼要有非規格化的數呢?(1),非規格化的數提供了一種表示0的方法,在規格化數中,尾數M總是大于等于1的,因此無法表示0。由于符号位的存在,因此浮點數表示中存在 0.0和-0.0。(2),非規格化的數可以表示那些非常接近于0.0的數,它們可以逐漸溢出(gradual underflow), 使其數值分布均勻地接近于0.0。
- 特殊值
當e = 255 時, 如果m= 0,則表示無窮大。S=0時表示 ∞,s=1時表示-∞。如果m ≠ 0, 則表示NaN。比如在進行除0時得到的結果就可以用NaN表示。它還可以在某些應用中表示未初始化的數據。
以上就是浮點數是如何在計算機中表示的,這裡再舉一個例子說明一下:
比如這裡 有個32bits的二進制數00101010000111000100000000000000,那麼它表示的浮點數是多少呢?根據前面的知識我們來進行下面的分析,32bits表示的是一個單精度的浮點數, 因此進行s, e, m三部分劃分。下圖展示了計算全部過程:
計算過程
Reference:Computer Systems: A programmer’s Perspective
,