1. 程式人生 > 其它 >IEEE浮點數

IEEE浮點數

IEEE浮點數

在這節課中講解了有關於浮點數的相關內容,對我來說在理解上比整數的補碼錶示要複雜的多,這裡總結一下課上的內容以及自己的一些理解。

首先要知道對於小數來說,二進位制只能準確表示形如x/2^k這種有理數,不滿足這種形式的數需要迴圈重複位才能被準確表示,但是計算機的位數始終是有限的,因此這些數無法被準確表示。

另外,在有限的位數中,小數點的位置會對錶示數的範圍以及表示的數的精度產生影響。比如小數點靠左的話,所能表示數的範圍就變小了,但是因為小數點右邊的位數增加,因此所能表示的小數精度上升了。反之,同理。

基於上述描述,選用了浮點數這一折中的方法。浮點數的一般形式:(-1)^S×M×2^E

。其中,

  • S表示符號位,決定浮點數的正負,對於數值0也分正負0這種特殊情況
  • M表示尾數,是一個二進位制小數
  • E表示階碼

浮點數的位被劃分為三個欄位,分別對上述欄位進行編碼。符號位s直接編碼符號位S,k位的階碼編碼階碼E,剩下n位數字編碼尾數M,這個編碼出來的數值也與階碼是否為0有關,後續會介紹到。

下面以C語言中的單精度浮點數(即float)來舉例說明計算機中對於浮點數的編碼。
對於32位的浮點數,最高的一位用於表示符號,接下來的8位用於編碼階碼,最後23位用於編碼尾數。對於符號位的編碼很容易,0表示正數,1表示負數。根據k位的階碼的值的不同,被編碼的值可以分成三種情況:規格化的值,非規格化的值以及特殊值。下面將分別介紹這三種,並在最後給出總結。

1. 規格化的值。

規格化的值的特點是用於編碼階碼E的k位的數值既不全為0,也不全為1。在這裡,階碼E被表示為E = e - Bias。e則是計算機中k位無符號數,取值範圍在0-255(對於float而言)之間,Bias則是一個值為2^(k-1)-1的偏置值,因為這種設定,階碼所能取到的值剛好使得0處於中間位置。剩下用於表示尾數的小數字段f,則M=f+1,相當於有一個隱含的以1開頭的表示,因此M的範圍就是M>=1 && M < 2。

2. 非規格化的數。

當階碼域,即e全為0時,表示的數是非規格化形式。此時階碼值E=1-Bias,尾數M=f,並不包含隱含的1

這裡使階碼值為1-Bias而不是直覺上的-Bias,是為了提供一種從非規格化值平滑到規格化值的方法。舉個例子說明這種平滑過渡:假定有8位格式,一位符號位,4位階碼和3位尾數,那麼最大的非規格化值則是7/512,最小的規格化值則是8/512,實現了平滑過渡。

非規格化數有兩個用途:

  1. 提供了一種表示0的方法。由於規格化數的尾數部分始終大於等於1,因此無法表示0。那麼這時候就會產生符號位為0/1,階碼域與尾數域均為0的+0.0與-0.0的情況。書中沒有具體說明兩者不同與相同的情況,只是說了在某些方面被認為是不同的,在某些方面是相同的。
  2. 另外一個功能是表示那些非常接近0.0的數。這裡提到了一種稱為逐漸下溢(gradual underflow)的屬性,使可能的數值均勻地接近於0。

查了一點有關於逐漸下溢的內容,從字面上理解就是一個逐漸朝會下溢的方向走,但是如果使用之前提到的規格化值是無法實現這個目的的,因此誕生了非規格化數來實現這個不斷接近0的過程,就可以表達出更小的數字了

3.特殊的值

特殊值指的是階碼域全為1的時候。此時,當小數域全為0時則表示無窮,符號位為0是正無窮,符號位為1是負無窮。無窮能夠表示溢位的結果。如果小數域不為0,結果值被稱為NaN(Not a Number)。

到這裡就介紹完了C語言中浮點數的表示的介紹,可以看到前人在表示小數上的智慧,通過一系列設計使得計算機表示小數的方式更加合理。接下來,將介紹浮點數在實際計算中的一些性質,主要是介紹舍入以及浮點數運算的基本情況。

舍入

根據IEEE的標準,有四種舍入方式:向上舍入,向下舍入,向0舍入,向偶數舍入。其中向偶數舍入有其統計學上的意義,即50%的情況下向上舍入,50%的情況下向下舍入。在支援IEEE浮點數的機器上,使用向偶數舍入的舍入方式。

這裡是否是偶數只考慮最低有效位是否是偶數

浮點數運算

浮點數運算中,令我印象最深刻的則是加法/乘法均不符合結合律。

(3.14+1e10)-1e10 != 3.14 + (1e10-1e10)

但是浮點數加法/乘法滿足單調性,這是無符號數或者補碼的加法/乘法所沒有的。

單調性即,如果a >= b,那麼對於任何的a,b,x(除了NaN),都有x+a>=x+b

C語言中,在進行型別轉換時,int->double不會有損失,而int->float時,由於int的位數比float的尾數位數多,因此會出現舍入。

總結

這篇筆記基於《深入理解計算機系統》以及作者相應的課程。有關於浮點數值得探究的內容還有很多,這裡只是做了個一個大致的介紹,在遇到實際的問題時,還需要具體問題具體分析,結合語言特點解決問題。比如C語言的標準並不要求機器使用IEEE浮點,因此沒有標準的方法來改變舍入方式或者得到-0,+∞、-∞或者NaN之類的特殊值。

參考資料

深入理解計算機系統原書第三版