浮點數運算案例


前面有寫過一篇面試題博文 0.1+0.2 是否等於 0.3。裏面也涉及到浮點數運算。本文來詳細列舉一個浮點數運算案例。

浮點數運算五個步驟

1. 對階
原則是小階對大階。
如 0.000101 的科學記數法爲 1.012^-4 。
而 0.0101 的科學記數法爲 1.01
2^-2 。
小階就是 -4,大階就是 -2。
這裏需要把 -4 調整成 -2。則 0.000101 的科學記數法爲 0.0101 2^-2 。
階數相同了,就可以進行尾數運算。
那麼爲什麼不用大階對小階暱。如果把 0.0101 的科學記數法調整爲 1.0
2^-4。這樣就是高位移出。損失的精度更高。

2. 尾數運算
對階完之後,就可以將尾數進行運算了。

3. 規格化
規格化指的是對於 IEEE754 標準的浮點數來說,尾數必須是1.M的形式。
規格化操作分爲左規和右規兩種情況。
左規指的就是小數點往左移動,比如 0.000101 變成 1.012^-4。
右規指的就是小數點往右移動,比如10.001 變成 1.001
2^1。右規一般只移動一位,發生在進位的情況下。比如二進制 11+1 = 100。

4. 舍入處理
舍入其實就是四捨五入。溢出的數爲 0 則直接捨去,爲 1 則加1。
比如二進制 011110011 只要保留 8 位。因爲最後一位尾數是1,則 01111001+1= 01111010。而 二進制 011110010 如果保留 8 位。最後一位尾數是0,直接捨去。結果爲 01111001。

5. 溢出判斷
溢出判斷指階碼值是否產生溢出。
若階碼值超過了階碼所能表示的最大正數,則爲上溢。若此時浮點數爲正數,則爲正上溢,記爲+∞,若浮點數爲負數,則爲負上溢,記爲-∞。
比如用 8 位表示階碼值。則範圍爲 2^8-1=255。要考慮負數的情況下,範圍爲 -127-127,此時的階碼值如果是 128。就是上溢。

若階碼值超過了階碼所能表示的最小負數,則爲下溢,若此時浮點數爲正數,則爲正下溢,若浮點數爲負數,則爲負下溢。正下溢和負下溢都作爲0處理。
同樣如果用 8 位表示階碼值。存在負數的情況下,範圍爲 -127-127。而此時的階碼值如果是-128。就是下溢。

案例

下面我們來計算一下 0.3+1.6 = 1.9000000000000001。

將 0.3 轉換二進制。浮點數轉二進制是乘2取整數部分。

0.3*2=0.6
0.6*2=1.2
0.2*2=0.4
0.4*2=0.8
0.8*2=1.6
0.6*2=1.2(從這裏開始循環1001)

結果爲 0.0100110011001100(1001)…(1001部分無限循環)
規格化爲:1.001100110011… * 2^-2

將 1.6 轉換二進制。浮點數轉二進制是乘2取整數部分。

0.6*2=1.2
0.2*2=0.4
0.4*2=0.8
0.8*2=1.6
0.6*2=1.2(從這裏開始循環1001)

結果爲 1.1001100110011001(1)…(0011部分無限循環)
規格化爲:1.100110011001… * 2^0

1. 對階
0.3 的階數爲 -2,1.1 的階數爲0。所以把 0.3 還原爲 0.01001100 * 2^0。

2. 尾數相加
因爲 64 位表示二進制需要四捨五入。
所以 0.3 的二進制需要進一位。
0. 0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100(1)
結果爲
0. 0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1101

同理1.6 的二進制也需要進一位。
1.1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001(1)
結果爲
1.1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010

相加:
0. 0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1101
+1.1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010
1.1110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0111

3. 格式化
格式化指的就是1*M的形式,這裏已經是格式化的數據了。

4. 舍入處理
由於 0.3 二進制小數點右移了2位。且第一位爲1。所以需要進1。
結果爲
1.1110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 1110

5.溢出判斷
由於沒有溢出,這裏不需要做溢出判斷。

所以最後的結果用 64 位表示爲:
因爲是正數,所以首位用 0 表示。
整數部分爲 2^(11-1)-1+(-2)=1021。用二進制表示爲 01111111101
小數部分爲 1110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 1110
所以(0.3)+(1.6)=
0 01111111101 1110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 1110
轉換爲10進製爲:1.9000000000000001

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章