1. 程式人生 > >浮點數在計算機中儲存的方式

浮點數在計算機中儲存的方式

浮點數在計算機中的儲存

1996年6月4日,歐洲最新的無人駕駛火箭Ariane5初次航行時,發射後僅37秒,火箭偏離了它的飛行路徑,解體並且爆炸。火箭上載有價值5億美元的通訊衛星。科學家們進行調查之後,原來只是因為小小的浮點數導致這場災難性的後果,白白地損失了5億美元。
作為這場事故的肇事者浮點數,它轉換成整數時發生了溢位。在Ariane5的控制慣性導航系統的計算機向控制引擎噴嘴的計算機發送了一個無效資料,本應該傳送飛行控制資訊,而是傳送了一個診斷位模式。表明將一個64位浮點數轉化成16位有符號整數時,產生了溢位。
現今計算機都採用IEEE標準下的浮點數規則,方便在不同機器上的可移植性。

一.浮點數的表示:

IEEE浮點標準表示:V=(-1)^s*M*2^E。

符號(sign):s決定這個數是負數(s=1)還是正數(s=0)
尾數(significand):M是一個二進位制小數
階碼(exponent):E的作用是對浮點數加權,權重是2的E次冪
將一個浮點數的位分解成3個欄位,分別對這些欄位進行編碼:
1. 單獨的符號位s佔1位;
2. k位的階碼欄位exp編碼階碼E;
3. n位小數字段frac編碼尾數M.
C語言中的float,s佔1位,k佔8位,n佔23位,加起來32位,即4個位元組。double型別的s同樣佔1位,只是k和n佔的位數和float不同,但是計算方式一樣。以下例子以float為準。
例子1:浮點數125.125D = 1111101.001B,轉化規則為:先將二進位制小數用二進位制科學記數法表示,即1.111101001*2^6,指數E=6,因為該數為正,所以符號位s=0,由於k=8,因此偏移量Bias=2^(k-1)-1=127,所以階碼欄位e=E+Bias,為133,即10000101。M=1.111101001,frac表示尾數,即科學計演算法小數點後面的部分,不足23位補0。因此32位浮點數125.125在計算機中表示為01000010111110100100000000000000。8位的指數可以表示0-255指數值,但是如果指數為負則表達不了,所以Bias存在的原因為了處理指數為負的情況,這樣可以表達的指數值範圍就變成了[-127,128]之間。即exp=E+Bias。
浮點數在IEEE標準下又分為3類:
1. 規格化的值:當exp階碼欄位不全為0也不全為1。M=1+frac。上面的例子既是規格化的值。
2. 非規格化的值:exp階碼欄位全為0時,在這種情況下,實際的E=0,但是表示時為E=1-Bias而不是E=0-Bias,這是為了更加平滑地將非規格化值轉化為規格化值。M=frac。
3. 特殊值:exp階碼欄位全為1時稱為特殊值。當小數域全為0時,得到的值為無窮。小數域為非零時,結果值稱為NaN,不是一個數,比如根號-1。
平滑地將非規格化值轉化為規格化值解釋:
假如k=4,n=3,最大的非規格數為0 0000 111,由此可得E=1-(2^(k-1)-1)=-6,2^E=1/64,frac=1/2+1/4+1/8=7/8,M=frac,所以V=(-1)^0*2^E*M=7/512。最小的規格數為0 0001 000,E=1-(2^(k-1)-1)=-6,2^E=1/64,frac=0/8,M=1+frac=1。V=8/512。
最大的非規格數為7/512,最小的規格數為8/512,完成了平滑的轉換,如果非規格數種E=-Bias,那麼最大的非規格數應該為7/1024。
非規格數有兩個作用:
1. 可以表示0
2. 表示那些非常接近0.0的數,非規格數在最小規格數和0之間可以表示大量的小數。

二.舍入

IEEE標準表示的浮點數限制了浮點數的範圍和精度,,因為需要將值x匹配到對應的x’,這就是舍入
IEEE浮點格式定義了4中不同的舍入方式,預設的舍入方式是找最近的匹配。其它3種分別為向上舍入、向下舍入、向零舍入。
最近匹配:又稱向偶數舍入。找到一個最接近的匹配值,比如1.2舍入為1.0,但是如果是兩個可能的中間值的話就需要一種判斷方法,定義為總是向最低有效數字為偶數舍入。比如1.5舍入成2.0。這種方法運用於二進位制小數時,最低有效位的值0認為是偶數,1認為是奇數。比如舍入到小數點後2位(最近的匹配值為1/4,即每次按1/4來舍入),10.00011(2*(3/32))向下舍入為10.00(2),10.11100(2*(7/8))向上舍入成11.00(3)。

三.浮點運算

浮點數的運算計算出來的值其實並不是算出來是多少就是多少,因為浮點數表示的範圍和精度都有限,所以會進行舍入,匹配到一個值。舉個例子,假如0.1+0.2=0.3,但是浮點數的表示中沒有0.3這個值,那它會將0.3按最近匹配匹配到一個可以表示的值進行輸出。所以在程式中,這種誤差如果累積下來,計算出來的結果可能偏差會極大。另外浮點加法不具有結合性,即(a+b)+c不一定等於a+(b+c),因為過程中可能會出現舍入。浮點乘法不具有結合性和分配性,原因也是舍入或者溢位。

總結:

回到Ariane5爆炸的原因,浮點數為64位,k=11,既可以表示2^(e-Bias)這麼大,Bias=2*(k-1)-1=2013,即可表示2^(2^12-1-2-13)=2^128次方,有符號整數為16位,最大可以表示2^15-1。只要速率變大,會溢位是很正常的事,所以說。。。。老司機要注意速度,不要動不動就飆車,哈哈。