今天學習了浮點數運算(加減乘除)。浮點數運算主要包括兩部分:指數運算和尾數運算。在ieee754標準下,指數運算就是階碼的運算,類似於無符號數運算。尾數運算是原碼運算。之前一直很疑惑為什麼前面的教材在介紹原碼運算(加減乘除)所舉的例子都是小數運算。現在猜想那部分內容可能只是為了浮點數運算做鋪墊,這裡才是主要的內容。(當然知識是不分重點的,但考試分)。下面就來詳細介紹下浮點數運算的過程吧!另外本文使用的浮點數標準均為ieee754結構,即單精度數由1位符號位,8位指數字,23位尾數字共計32位組成。
浮點數的加減運算分為5個步驟:對階、尾數相加、尾數規格化、尾數捨入處理、溢位判斷處理。下面詳細介紹:
1. 對階:
所謂對階,就是讓兩個運算元階數相同,以便進行加減。實現的方式是對較小數的尾數進行右移操作。對階的原則是向高階看齊。計算公式為:
當結果大於0說明被加數(被減數)階數高,則對加數(減數)進行移位對階。小於0則反之改變被加數(被減數)。
2. 尾數加減:
將兩個運算元的尾數相加減。值得注意的是:在ieee754標準中,對於規格化數來說在小數點前有一位隱藏位1,在加減過程中需要把它還原到尾數中。尾數加減的實質是原碼的加減,對於原碼加減的規則如下圖所示:
3. 尾數規格化:
加減完成的尾數形式未必滿足ieee754對於尾數的要求,即保留23位,小數點在第乙個1之後。需要對尾數進行左規和右規,下面介紹一下左規和右規。
左規:將尾數向左移,用於清除第乙個1前面出現的0。左規伴隨著階碼減少,在左規過程中要檢測階碼是否發生下溢,即階碼達到最小值(0000 0000)。
右規:將尾數向右移,用於兩數相加後出現向高位進製的情況。因為兩數相加最多進一位,所以右規最多一位。右規伴隨著階碼的增加,在右規過程中要檢測階碼是否發生上溢,即階碼達到最大值(1111 1111)。
4. 尾數的捨入處理:
在對階和右規的時候,最右邊的數字會被移出。為了保證最後計算的精度,把這些數字在過程中儲存,等到最後進行捨入。也就是我上文提到的附加位。有兩個問題值得注意:
1) 保留多少附加位合適?
2)最終對附加位怎麼進行捨入?
在ieee754中保留了保護位,捨入位,粘位三位作為附加位。同時對於ieee754來說最後附加位的捨入,有如下規則:
5. 溢位判斷:
在浮點數中是以階碼的溢位與否來作為評判標準的。單精度溢位分為上溢(指數大於等於127)和下溢(指數小於等於-126)。
插一句:「之前一直以為下溢的指數是-149,這個數字**於-126再把所有的尾數向右移,當到達-149時剛剛好所有尾數全部為零,即表示零。這個誤區在於沒有正確的區分規格化數和非規格化數。對於規格化數而言,下溢就是-126,所以規格化數表示的最小值為1.00…乘2的-126次方,而0~0.111…乘2的-126次方就是非規格化數表示的範圍。-149正是非規格化數表示的最小範圍。這裡貼一張圖,更加便於理解。
下面直接貼上乙個書上的例項,對以上過程進一步加深了解:
浮點數乘除和定點數乘除相同,在正式運算前會對運算元進行預處理。對於乘法如果有乙個運算元為0則結果為0。對於浮點數除法,若被除數為0,則結果為0。除數為0分兩種情況,第一種是被除數非零,第二種是被除數為0。下面著重介紹一下兩種除數為0:
除數為0,被除數不為0:
結果為無窮大。在ieee 754標準下就是階碼全為1,尾數全為0。c語言輸出如下圖:
除數為0,被除數為0:
結果是nan(not a number)。在ieee 754標準下就是階碼全為1,尾數非0。在c語言中輸出如下圖:
注:在windows系統下,-1.#ind00即代表nan,linux系統下會輸出nan。
下面詳細介紹無特殊情況浮點數的乘除運算:
浮點數乘除運算公式如下圖:
1.浮點數的乘法:
1)尾數相乘,指數相加:
尾數相乘即為原碼相乘,這個具體的過程請參考另一篇文章:定點數運算(於文末給出**)。值得注意的是,對於規格化浮點數要記得恢復隱藏位。指數相加可以直接運用移碼的計算方法:
2)尾數規格化:
對於兩個運算元的尾數一定都是大於1的(隱藏位導致),所以最終得到的結果,小數點前會有兩位共三種情況(01,11,10)。若為01則不需規格化,11和10則需右規一位。注意對於ieee754標準浮點數乘法不需要左規。
3)尾數捨入處理:
兩個小數相乘,尾數自然更多,但位置是有限的,需要對尾數進行捨入,具體的捨入規則參照浮點數加減的捨入規則即可。
乘法的溢位有兩種可能:階碼相加減時,以及尾數右規時。右規與上文相同,下面介紹一下階碼溢位的判斷標準:
注:eb是最終的結果,ex和ey是運算元的指數值。
2.浮點數除法:
浮點數除法大致分為4步:尾數相除階相減、尾數規格化、尾數捨入、溢位判斷處理。由於除法大部分與乘法相似,所以此處只列出不同部分。
在尾數相除階相減過程中,尾數除法也在上文引用那篇文章中有具體介紹。階碼相減的運算公式如下:
在尾數規格化步驟中:當除法運算完成後,若小數點前為0,則需進行左規以保證小數點前具有隱藏位1。
對於除法階碼溢位判斷的規則如下:
注:eb為最終結果指數,exey為運算元指數。
補充:在《程式是怎樣跑起來的?》書中,對於階碼為什麼使用0-127做了乙個原因的解釋:在計算機中,使用excess系統的方法來同時儲存正數和負數。這裡面的0-127就是增加幻數之後的數字。幻數選擇了127,可記為excess_127。
本篇文章對於浮點數運算進行了介紹,因為作者水平有限,可能某些地方理解錯誤,請高手不吝賜教,批評指正,謝謝!
浮點數運算
浮點數運算的公式 n m re n代表浮點數 m代表尾數 r代表基數 e代表指數 所謂浮點數就是類似我們高中學的科學計數法 比如 1000 就表示為 1.0 103 那麼浮點型計算就是兩個用科學計數法表示的數之間進行的計算 例如 1.0 102 1.19 103 該如何計算 步驟 1.對階 所謂對階...
php 浮點數運算
php r echo 0.1 0.7 0.8 true false 了解浮點運算的都不難理解以上 執行時會得到false 這是因為很多的10進製數都不能精確的轉成2進製,或如果要精確轉換的話需要的二進位制數太長,會捨棄掉末尾部分,只儲存一定的精度。比如0.1 十進位制 0.0001100 1100 ...
浮點數的運算
規格化的浮點數因為儲存是使用類似科學計數法的表示,因此計算方法大體上與科學計數法較為類似。浮點加減法的一般步驟 減法本質也是加法 對於二進位制形式的兩個浮點數相加 1.對階 對於兩個規格化浮點數,將較小的指數的數向較大指數的數對齊。通過移動小數點實現。如果出現有效數字位數不能滿足的情況,進行近似。2...