浮点数详解(一篇彻底学通浮点数)
文章目錄
- 浮點數
- 一.什么是浮點數
- 二.浮點數的形式
- 1.非規格化浮點數
- 2.規格化浮點數
- 三.IEEE754標準浮點數
- 1.單精度浮點數
- 2.雙精度浮點數
- 四.浮點數的運算
- 1.浮點數的加減法
- 2.浮點數的乘除法
- 五.C語言中的浮點數分析
浮點數
一.什么是浮點數
浮點數是與定點數相對的概念,計算機中的定點數約定小數點的位置不變,即人為約定俗成地規定了一個數小數點的位置。例如定點純整數約定了小數點在數值位的最后。定點純小數約定了數值位的最高位在小數點后面。
由于計算機字長的限制,當需要表示的數據有很大的數值范圍時,他們不能直接用定點小數或者定點整數表示
二.浮點數的形式
浮點數由尾數M和階碼E構成。基數為2的數F的浮點數表示為:
F=M?2EF=M*2^EF=M?2E
浮點數編碼規則:
- 尾數M必須為小數,用n+1位有符號定點小數表示,可采用的原碼,補碼。階碼E必須為整數,用k+1位有符號定點整數表示,可采用原碼,補碼,移碼。浮點數編碼的位數m=(n+1)+(k+1)
- 浮點數的編碼格式有多種,格式的選擇可由計算機設計人員決定,例如:
| 1 | k | 1 | n |
其中:
(1)階碼是整數,其位數k+1決定了浮點數表示的數值范圍,也就是決定了數據的大小,或小數點在數據中的真實位置。階符決定階碼的正負。即階碼越長,所能表示的范圍越大
(2)尾數是小數,其位數n+1決定了浮點數的精度,如果尾數采用小數且位數n足夠長,則當浮點數運算需要對尾數運算結果舍入時,造成的數據精度損失會比較小。即尾數越長,所能表示的精度越高
(3)尾數的符號表示浮點數的正負。
1.非規格化浮點數
當對尾數M只要求是小數而無其他限制時,此時的浮點數被稱為非規格化浮點數。
假設階碼和尾數都用補碼表示,則非規格化浮點數可表示的范圍如下:
| 階碼最小值 | ?2k-2^k?2k | 階碼最大值 | 2k?12^k-12k?1 |
| 尾數最小負值 | -1 | 尾數最大負值 | ?2?n-2^{-n}?2?n |
| 尾數最小正值 | +2?n+2^{-n}+2?n | 尾數最大正值 | +(1?2?n)+(1-2^{-n})+(1?2?n) |
以8位數值位,一位符號位的階碼為例子: 由于用補碼表示,
所以階碼的最小值應該為:1 00000000 即 -2^8 = -256
而階碼的最大值應為:0 11111111 即 2^8-1 = 255
再來分析尾數的情況,假設尾數也是8位數值位,1為符號位補碼的形式:
由于我們限定了浮點數的尾數只能是小數,所以我們當成定點純小數的形式進行分析:
1.00000000表示了-1的補碼,即尾數的最小負值
1.11111111 表示了 ?2?n-2^{-n}?2?n的補碼,即尾數的最大負值,其原碼是1.00000001
0.11111111表示了+(1?2?n)+(1-2^{-n})+(1?2?n)的補碼(原碼),即尾數的最大正值
0.00000001表示了+2?n+2^{-n}+2?n的補碼(原碼),即尾數的最小正值
當然0.00000000表示0,是其最小絕對值
2.規格化浮點數
為了使有限字長的二進制尾數能表示更多的有效數位,同時使浮點數有統一的表示形式,浮點數通常采用規格化形式來表示。
規格化浮點數要求將尾數M的絕對值限定在規定的數值范圍之內,即
12≤∣M∣<1(對于原碼而言)\frac{1}{2}\le|M|<1(對于原碼而言)21?≤∣M∣<1(對于原碼而言)
要使尾數的絕對值在此范圍內,通過改變小數點的位置(相應地改變階碼)就可以做到。
為什么要這樣做,我們舉一個最簡單的例子,假如一個尾數M用原碼表示為:
0.00101000,那么這8位尾數的前2位都是0,這2個0實際上是無效數值位,我們完全可以改寫成: 0.101000xx×2?20.101000xx \times2^{-2}0.101000xx×2?2 當1左移到最高位時,尾數后面多出來了兩位可以多表示兩個有效位來提高精度(尾數越長,浮點數精度越高)
例如同樣要表示1101.1000000這個數,那么我們可以有這樣的不唯二的兩種表示形式:
(1)0.11011000×24(1)0.11011000\times2^4(1)0.11011000×24
其中尾數是0 .11011101,階碼是0 0100
(2)0.00110110×26(2)0.00110110\times2^6(2)0.00110110×26
其中尾數是0 .00110110,階碼是0 1100
(1)和(2)中,(1)是規格化浮點數,而(2)不是規格化浮點數
若尾數M用補碼表示,
則當M≥\ge≥ 0時,規格化尾數的形式必須為:
[M]補=0.1XXXXXXX[M]_補=0.1XXXXXXX[M]補?=0.1XXXXXXX
則當M< 0時,規格化尾數的形式必須為:
[M]補=1.0XXXXXXX[M]_補=1.0XXXXXXX[M]補?=1.0XXXXXXX
其中X為任意二進制值
?注意(重點)?:
- 以上形式才是判斷浮點數是否規格化的一般方法:看尾數補碼的符號位與數值為最高位異或是否為1(即符號位與數值最高位不同)
- 判斷浮點數是否規格化的根本思想是:尾數數值位首位必須以有效位開頭
- 對于正數補碼(原碼)而言,有效位為1;對于負數補碼而言,有效位為0
- 基于以上判定準則,尾數-1(補碼)是規格化形式;尾數-1/2(補碼)不是規格化形式,注意不要與原碼規格化判定的絕對值范圍混淆
三.IEEE754標準浮點數
1.單精度浮點數
IEEE 754規定單精度浮點數的真值一般表示為:
N=(?1)s×2e?127×1.fN=(-1)^s\times2^{e-127}\times1.fN=(?1)s×2e?127×1.f
單精度浮點數編碼格式由三個字段構成:
- 數符s為1位,表示浮點數的正負
- 尾數編碼f為23位(采用原碼表示)
- 階碼編碼e為8位(含1位階符,采用移碼表示,偏移量127)
其中需要注意的是:
(1)IEEE 754中的階碼采用移碼來表示,但對于單精度浮點數來說,移碼的偏移量不是272^727而是27?1=1272^7-1=12727?1=127,這是因為IEEE 754將移碼編碼的全0和全1作為了特殊標識。
(2)IEEE 754浮點數是規格化浮點數,為了能夠更多地表示尾數的有效數位,規定尾數真值的整數部分必須為1,尾數編碼時整數1隱去,小數部分f用原碼表示。
對于階碼e全0和全1時的特殊含義:
- (1)當階碼全0,且尾數f不全0時,表示該浮點數不是規格化浮點數,尾數實際為:
0.XXXXXXXX(次正規數)0.XXXXXXXX(次正規數)0.XXXXXXXX(次正規數)
\space \space \space\space????而不是規定形式的:
1.XXXXXXXX1.XXXXXXXX1.XXXXXXXX - (2)當階碼e全1,且尾數f全為0時,則該浮點數表示正無窮大或負無窮大,當數符s為1時,表示負無窮大,當數符s為0時,表示正無窮大。
- (3)當階碼e全1,且尾數f不全為0時,則該浮點數表示非數值數據(NaN)。
總結.對于單精度浮點數:
(1)階碼的真值E=e-127,并且0<e<255,-126<E<127。
(2)當e=0或255時,在IEEE 754中表示特殊的數。
(3)所能表示的范圍為:
正數為:+2+127×(1+1?2?23)到+2?126×(1+0)正數為:+2^{+127}\times (1+1-2^{-23})到+2^{-126} \times (1+0)正數為:+2+127×(1+1?2?23)到+2?126×(1+0)
負數為:?2+127×(1+1?2?23)到?2?126×(1+0)負數為:-2^{+127} \times (1+1-2^{-23})到-2^{-126}\times (1+0)負數為:?2+127×(1+1?2?23)到?2?126×(1+0)
2.雙精度浮點數
簡要說明雙精度浮點數(與單精度浮點數相類似):
(1)階碼的真值E的取值范圍為:-1022 ~ +1023,偏移量為+1023,階碼移碼編碼e為:
+1 ~ + 2046
(2)雙精度浮點數的規格化數表示為:
N=(?1)s×2e?1023×1.fN=(-1)^s \times 2^{e-1023}\times1.fN=(?1)s×2e?1023×1.f
(3)所能表示的規格化數范圍:
正數為:+2+1023×(1+1?2?52)到+2?1022×(1+0)正數為:+2^{+1023}\times (1+1-2^{-52})到+2^{-1022} \times (1+0)正數為:+2+1023×(1+1?2?52)到+2?1022×(1+0)
負數為:?2+1023×(1+1?2?52)到?2?1022×(1+0)負數為:-2^{+1023} \times (1+1-2^{-52})到-2^{-1022}\times (1+0)負數為:?2+1023×(1+1?2?52)到?2?1022×(1+0)
(4)當e=0或e=2047時,在IEEE 754標準中表示特殊的數
浮點數的舍入規則:
1、就近舍入
2、朝0舍入
3、朝正無窮舍入
4、朝負無窮舍入
可以參考博文:IEEE754標準中的4種舍入規則
IEEE754浮點數的下溢
四.浮點數的運算
1.浮點數的加減法
假設有兩個浮點數:
X=Mx×2ExX=M_x \times 2^{E_x}X=Mx?×2Ex?
Y=My×2EyY=M_y \times 2^{E_y}Y=My?×2Ey?
- (1)對階:尾數右移,小階對大階,階碼小的尾數右移,階碼+1
- (2)尾數加減法運算:使用補碼運算,減法也采用補碼加法實現
- (3)規格化:尾數加減法運算后,結果可能是非規格化數。如果結果的真值M不滿足:1/2≤M<11/2 \le M < 11/2≤M<1,則是非規格化數需要規格化處理,根據情況分為以下兩種處理方式:
運算結果尾數的規格化處理(左規):
運算結果尾數的溢出處理(右規):
- (4)舍入處理:尾數右移時將舍棄尾數最低位:1)截斷法:直接將右移出的尾數低位丟棄。2)末位恒置1法:無論尾數右移丟棄的是1還是0,保證保留的尾數最低為永遠為1。3)0舍1入法:規則如下圖所示
浮點數加減法例題:
求解過程:
2.浮點數的乘除法
浮點數的乘法
浮點數的除法
浮點數規格化總結:
五.C語言中的浮點數分析
下面是一段c語言代碼:
float a = 12.5; int *p =(int *) &a;int b=*p;printf("b的值為:%d",b);程序的執行結果是這樣的:
我們來思考一下程序為什么會得出這樣的結果,其實和IEEE 754單精度浮點數的存儲規則密切相關:
學過c語言指針的同學不難看出,上面的代碼不過是將單精度浮點數a 4個字節的存儲空間中的所有數以整數int形式讀出了而已。
下面我們根據IEEE 754單精度浮點數的規則,來推斷12.5在4個字節的存儲空間里是以怎樣的二進制形式存放的。
IEEE 754單精度浮點數規定,1位數符,8位階碼(移碼),23位尾數(原碼)。
那么12.5的
-
數符s為:0
-
尾數為:10010000000000000000000(原碼1.1001的小數部分:.1001)
-
階碼為:10000010(階碼真值為3,移碼為:3+127=130)
所以,整個32位的浮點數為:
01000001010010000000000000000000
將得到的二進制形式轉換為10進制查看:
轉換之后與程序得出的結果一致,這就證明了C語言中float類型確實采用了IEEE 754單精度浮點數的標準。 -
補充內容:IEEE754浮點數的漸進下溢
-
補充內容:浮點數精度丟失分析
總結
以上是生活随笔為你收集整理的浮点数详解(一篇彻底学通浮点数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LM317的直流可调稳压电源Multis
- 下一篇: 测试111111111