通過上章,我們知道,4.25的二進制是100.01,4.75 = 100.11。
但仔細想想,就會覺得不對勁,
浮點是不是隻能表示1被2或2的倍數除的小數和呢?
帶着這個疑問,我們來拜訪下4.1,這次我們和4.125以及4.0625一起來拜訪
0 12345678 12345678 12345678 1234567
0 10000001 00001000 00000000 0000000 4.125
0 10000001 00000110 01100110 0110011 4.1
0 10000001 00000100 00000000 0000000 4.0625
在打印裏,我們發現4.1大於4.0625,小於4.125.這也符合我們的常識。
其中4.625和 4.125和4.25一樣比較特殊,都可以表示1被2或2的倍數除的小數和呢.所以在二進制裏,它的描述很簡單,很快就到了盡頭。
但是4.1就不一樣了,無論怎麼搞,會發現都無法找到盡頭,如果位數是無限的,它可以搞到無限位,但最終都是越來越接近1,就像高等數學的極限一樣,下面類似下面這個公式
1 = 1/2 + 1/4 + 1/8 +......1/n+.......
可是你雖然無限位,但電腦存儲可達不到無限位了,怎麼辦呢?這就牽涉到精度的問題了。
規定只存儲一定量的尾巴,多餘的尾巴不要。
如float類型,尾數位置是32-8-1 = 23尾。
那麼它只能存儲23位的尾數,所以這就是它的精度,再往後的無限循環或者有限的尾巴我就不表示了,我就表示這麼多。
那麼由此我們可以得出,double類型雙精度確實比float精度要高的多,因爲它的尾數位更長。
可以這樣又引出了另一個問題。
我們來嘗試打印一下4.0999999f的位
0 12345678 12345678 12345678 1234567
0 10000001 00001000 00000000 0000000 4.125
0 10000001 00000110 01100110 0110011 4.10 10000001 00000110 01100110 0110011 4.0999999f
0 10000001 00000100 00000000 0000000 4.0625
這時候就會發現,我去,這4.1和4.0999999是一模一樣的嗎?
不,它們不是一樣的,只是可憐的是,它們在有限的23尾內是一樣的,float類型就只能存儲這麼多
我們再測試一下這個:
System.out.println(4.1f == 4.0999999f);
結果是true
哈哈哈哈~~~是不是再也不敢再用浮點數據類型了?
well,沒有辦法,就是這樣,你平時所用的浮點數據類型就是這樣,它不會考慮精度之外的數,因爲本身它也從來沒有存儲過。
事實上,System.out.println(4.1f == 4.0999999f);這句會報黃線,編譯器認爲是沒有意義的代碼。相當於true==true
這個時候,我們再來看看第一章的一個現象:
System.out.println(0.05 + 0.01);
0.060000000000000005
爲什麼會出現這種現象呢?現在就可以推測解釋了。
在計算機裏,不是0.05+0.01,很有可能是0.049999999998 + 0.01000000007(數據不準,只是說明思想)
看到浮點數如此坑爹,有的同學可能不淡定了,那該怎麼辦呢?
我平時該怎麼對浮點型的數據進行運算呢?請看下一章。