看一個面試題考察面試者對浮點數(shù)存儲格式的理解
- 1代碼如下
public class Float_Double {
public static void main(String[] args) {
float f_v2 = 20.3f;
float f_v3 = 20.5f;
double d_v2 = 20.3;
double d_v3 = 20.5;
System.out.println(f_v2 == d_v2 ? "true" : "false");
System.out.println(f_v3 == d_v3 ? "true" : "false");
}
}
- 2 運行結果為:
false
true
浮點數(shù)存儲時經(jīng)過的步驟:
以 20.5轉換為例
- 1 將十進制浮點數(shù)轉換成二進制浮點數(shù)
1)先將整數(shù)部分轉換為二進制
20的二進制數(shù)值為 10100
2)將小數(shù)部分轉換為二進制
0.5 轉換二進制的方式:需要乘2取整數(shù)部分,然后用結果的小數(shù)部分繼續(xù)乘2缸血, 直到結果等于為0,或者到達位數(shù)极景。
0.5 * 2= 1.0 (1)
0 * 2= 0 (0)
0.5 的二進制數(shù)值為 0.10
3)所以20.5的二進制數(shù)值為10100.10 - 2 將二進制浮點數(shù)轉化為二進制浮點數(shù)的科學表示
科學表示法就是將浮點式表示為底數(shù)和冪數(shù)的形式
比如10100.10的科學表示法為1.01001E100
小數(shù)點后面的01001是底數(shù)
E后面的是冪數(shù)皆愉,100是4的二進制表示涝动,因為小數(shù)點向前移動了4位扣孟。 - 3 使用移位存儲算法進行冪位的存儲
1)float 類型良瞧,占4個字節(jié)计雌,32位悄晃,存儲結構如下:
對于float 數(shù)值來說, 指數(shù)位要加上127凿滤,即0111111(二進制)
上面20.5f的冪數(shù)是100妈橄,前面幾位補零:
00000100 + 01111111 = 1000 0011
最后20.5f在內存中的存儲結果為:
0-10000011-01001 00000 00000 00000 000
符號位-冪數(shù)-底數(shù),底數(shù)不足32位的后面補零
2)double 類型數(shù), 占8個字節(jié), 64位翁脆,存儲結構如下:
對于double 數(shù)值來說眷蚓, 指數(shù)位要加上1023, 即0111 111 111(二進制)
上面20.5的冪數(shù)是100,前面幾位補零:
000 000 0100 + 011 111 1111 = 100 000 0011
最后20.5在內存中的存儲結果為:
0-1000000011-01001 00000 00000 00000 00000 00000 00000 00000 00000 00000 00
符號位-冪數(shù)-底數(shù)反番,底數(shù)不足64位的后面補零
浮點數(shù)從內存中讀取出來后進行比較
- 1 現(xiàn)在看到20.5 轉換為float, double 的二進制數(shù)沙热, 冪數(shù)和底數(shù)是不同的
1)比較冪數(shù)時 float 型會-127, double型 會-1023,因此
float 型又變成了 0000100
double型又變成 0000000100
這時候比較,因為兩個木梳的位數(shù)不同罢缸,8位的數(shù)會在前面自動補0
2)比較底數(shù)時篙贸,float型數(shù)會自動在后面補0直至與double 型相同的52位
所以最終20.5f == 20.5的結果是true。 - 2 對于20.3f和20.3而言祖能,由于在十進制浮點數(shù)轉化為二進制浮點數(shù)時
底數(shù)部分一直無線循環(huán)歉秫,所以位數(shù)越多,也精確养铸,導致浮點數(shù)補零后比double類型的值小雁芙。
1)同理20.3 存儲為:
(float) 0-10000011-01001 10010 10011 00101 001(后面的舍去,因為float型只有32位)
(double) 0-1000000011-01001(后面循環(huán)1001, 直至尾數(shù)為52位)
2)20.3的float型二進制和double型二進制钞螟,符號位與指數(shù)位都相同兔甘,但是底數(shù)位不相同,float型到了23位之后都是0, double型一直1001循環(huán)到52位鳞滨。