十進位制浮點數的二進位制轉換及儲存
網上看到一道小題:
int main(void)
{
float a = 10.0;
double b = 10.0;
printf( "%d\n", a );
printf( "%d\n", b );
return 0;
}
輸出結果a,b均為0。
這道小題是一個很好的面試題,考查面試者對浮點數儲存的理解。
十進位制小數的二進位制表示:
整數部分:除以2,取出餘數,商繼續除以2,直到得到0為止,將取出的餘數逆序
小數部分:乘以2,然後取出整數部分,將剩下的小數部分繼續乘以2,然後再取整數部分,一直取到小數部分為零為止。如果永遠不為零,則按要求保留足夠位數的小數,最後一位做0舍1入。將取出的整數順序排列。
舉例:22.8125 轉二進位制的計算過程:
整數部分:除以2,商繼續除以2,得到0為止,將餘數逆序排列。
22 / 2 11 餘0
11/2 5 餘 1
5 /2 2 餘 1
2 /2 1 餘 0
1 /2 0 餘 1
得到22的二進位制是10110
小數部分:乘以2,取整,小數部分繼續乘以2,取整,得到小數部分0為止,將整數順序排列。
0.8125x2=1.625取整1,小數部分是0.625
0.625x2=1.25取整1,小數部分是0.25
0.25x2=0.5取整0,小數部分是0.5
0.5x2=1.0取整1,小數部分是0,
得到0.8125的二進位制是0.1101
結果:十進位制22.8125等於二進位制00010110.1101
浮點數的計算機儲存:
IEEE 754標準中所定義的單精度32位浮點數和雙精度64位浮點數的格式:
32位單精度
單精度二進位制小數,使用32位儲存。 1 8 23 位長 +-+--------+-----------------------+ |S| Exp | Fraction | +-+--------+-----------------------+ 31 30 23 22 0 位編號 (從右邊開始為0) 偏正值 +12764位雙精度
雙精度二進位制小數,使用64位儲存。 1 11 52 位長 +-+--------+-----------------------+ |S| Exp | Fraction | +-+--------+-----------------------+ 63 62 52 51 0 位編號 (從右邊開始為0) 偏正值 +1023單精度的E為指數值+127,雙精度的E為指數值+1023,IEEE標準要求浮點數必須是規範的,也就是說尾數的小數點左側必須為1,因此在儲存尾數時可以省略小數點左側的1,這樣實際上對於float型別我們是用了23bits表示了24bits尾數。
以32位單精度浮點數為例:
十進位制22.8125轉換為二進位制表示為00010110.1101,
00010110.1101 = 1.01101101 * 2^4
由此得出 符號位S為0,表示正數
指數位E為4+127=131D=10000011B
尾數F為1.01101101去掉小數點左側的1,即為01101101
這樣十進位制22.8125轉換為二進位制表示為00010110.1101,計算機儲存為01000001101101101000000000000000
01000001101101101000000000000000
1bit8bits23bits
S E F
符號位指數位尾數位
回頭再看最開始的小題,就容易多了。
10.0的二進位制表示為1010.0= 1.010*2^3
float型別的10.0:
符號位S為0
指數E為3+127=130=10000010
尾數F為010
double型別的10.0:
符號位S為0
指數E為3+1023=1026=10000000010
尾數F為010
最終結果:
float型別的10.0轉換為二進位制為1010.0儲存形式為01000001001000000000000000000000,16進製表示為0x41200000
double型別的10.0轉換為二進位制為1010.0儲存形式為0100000000100100後面用0補全,16進製表示為0x40240000
程式碼驗證一下:
int main(void)
{
float a = 10.0;
double b = 10.0;
int * pa = (int *)&a;
int * pb = (int *)&b;
printf( "%d\n", a );
printf( "%x\n", *pa );
printf( "%x\n", *(pb+1) );
return 0;
}
輸出結果:
$ ./a.out
0
41200000
40240000
IEEE 754 單精度浮點數轉換,線上計算http://www.styb.cn/cms/ieee_754.php