1. 摘要
在瞭解到C語言中整型是以二進位制補碼形式儲存在記憶體中後,我們不禁很好奇:那麼浮點型的資料是以什麼形式儲存在記憶體中的呢?
實際上,早在1985年,電氣電子工程師學會就制定了IEEE 754標準來解決單精度浮點數在計算機記憶體中的儲存問題。
那麼接下來,我們就以IEEE754-1985版來看一看浮點數在記憶體中的真實面目。
2. 浮點數的表達方式
2.1 浮點數的組成
浮點型家族中包含有:float、double、long double型別
IEEE 754標準下,一個浮點數V可以被拆解成三個部分
V = (-1) ^ S * f * 2 ^ E
- 1-bit sign S ------ 符號位S,用來表示正負
- Biased exponent e = E+bias:指數位,負責浮點數的大小
- Fraction f = · b1b2 … bp−1:小數位,負責浮點數的精度,且f大於等於1小於2
2.2 單精度浮點數
對於32位的單精度浮點數而言,記憶體中32個bit位是這樣分配的:
- 1位符號位
- 8位指數位
- 23位小數位
2.3 雙精度浮點數
對於64位的雙精度浮點數而言,記憶體中64個bit位是這樣分配的:
- 1位符號位
- 11位指數位
- 52位小數位
2.4 指數偏差(Biased Exponent)
2.4.1指數E不為全0或全1
對於float型,我們發現8位的E如果就表示8個無符號的二進位制位,那麼指數位2^E只能表示比1大的數,而不能表示0-1之間的數,這就導致負指數沒法被表示出來。
為了表示負指數,規定E在記憶體中的值等於你想要真實表達的指數的值再加上中間數127(對於double型,這個中間數是1023),所以即使你想使用負指數,加上127後E也還是非負的。
這就叫“指數偏差”。
2.4.2 指數位E全為1
1)小數位 f 不全為0
無論符號位s是什麼,浮點數V代表NaN
NaN 是 Not a number 的意思,代表了一個無法被表示出來的值,比如一個數除以0或負數的平方根
2)小數位 f 全為0
浮點數
V = ( −1)s∞
,此時表示正負無窮大
2.4.3 指數位E全為0
以下用單精度浮點數為例:
1)小數位 f 不全為0
V = (−1)s * 2−126 * (0.f)
2)小數位 f 全為0
V = (−1)s * 0 ,此時V表示正負0
2.5 小數位的規定(fraction)
小數位 f 是一個 [1,2) 間的數,所以 f 可以寫成以上圖片中的形式:1.xxxxx
由於 f 的第一位總是1,所以我們將第一位的1省略,這樣就能多表示一位小數點之後的數了
2.6 浮點數的範圍
浮點數的所能表達的最大值/最小值被定義在了標頭檔案<float.h>中
對於float型:
最小:2-126= 1.175×10-38
最大:2128 = 3.403×1038
對於double型:
最小:2-1022= 2.225×10-308
最大:21024 = 1.798×10308
3. 程式碼分析
讓我們來看一段程式碼來進行具體分析
#include<stdio.h>
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值為:%d\n",n);
printf("*pFloat的值為:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值為:%d\n",n);
printf("*pFloat的值為:%f\n",*pFloat);
return 0;
}
那麼執行結果是什麼呢?
不急,我們先對程式碼進行一波分析。
第一步
我們建立了一個int型變數n並賦值為9
第二步
我們將一個float型的指標變數pfloat指向了n
那我們就要問了:整型9在記憶體中是怎麼儲存的呢?
當然是以補碼形式儲存,所以這記憶體中的32個位元位是:
00000000 00000000 00000000 00001001
第三步
我們以%d(有符號整型)形式對上述32個位元位進行列印,顯然螢幕上應輸出:
n的值為:9
第四步
我們以%f(float型)形式對上述32個位元位進行列印
再看這32個位元位
00000000 00000000 00000000 00001001
我們重拾這個公式:V = (-1) ^ S * f * 2 ^ E 與 這張圖:
重新將上述32個位元位排序
0 00000000 00000000000000000001001
故 V = (−1)s * 2−126 * (0.00000000000000000001001)2,是一個很小很小的數,所以螢幕上預設列印小數點後六位的話,應輸出:
*pFloat的值為:0.000000
第五步
將pfloat指向地址的內容修改為9.0,顯然此時上述32個位元位中儲存的是單精度浮點數的二進位制表達方式,遵循IEEE 754標準
(9.0)10 = (1001.0)2 = (1.0010 * 23)2
所以上述32個位元位此時應該是:
0 10000010 00100000000000000000000
第六步
我們以%d(有符號整型)形式對上述32個位元位進行列印,顯然螢幕上應輸出:
num的值為:1,091,567,616
第七步
我們以%f(float型)形式對上述32個位元位進行列印,顯然螢幕上應輸出:
*pFloat的值為:9.000000
執行截圖如下:
4.參考文獻
1.IEEE Standard 754 Floating Point Numbers,geeksforgeeks
2.IEEE 754-1985,Wikipedia
3.Single-precision floating-point format,Wikipedia
4.IEEE Standard for Binary Floating-Point Arithmetic. 1985. doi:10.1109/IEEESTD.1985.82928. ISBN 0-7381-1165-1.
5.NaN,Wikipedia
注:來自維基百科參考文獻的快照若有需要,請聯絡本人
感謝你們的閱讀!本人水平有限,如有錯誤,還望指正!