您現在的位置是:首頁 > 攝影首頁攝影
一道正確率不足30%的Java面試題:浮點數如何正確使用
1.0是小數嗎
摘要
本文透過一道面試題來說明浮點數如何正確使用,防止在程式碼中不正確的使用導致業務異常。
在阿里的面試題中有這樣一道題:
據說這道題的正確率不足30%,很多人倒在了這道題上。這道題的正確答案是B,兩者並不相等。同時,根據這個題我們引申出一段常見的程式碼
這是一段錯誤的程式碼,程式碼並不會按照預期的效果進行。那正確應該怎麼使用呢?
1、指定一個誤差範圍,兩個浮點數的差值在此範圍之內,則認為是相等的。
2、使用 BigDecimal 來定義值,再進行浮點數的運算操作。
現在我們來分析一下,為什麼浮點數不能直接比較?
浮點數的二進位制表示
我們都知道,計算機是以二進位制儲存數字的。例如:十進位制的 8 在計算機中以110表示的。
那浮點數0。8如何表示呢?
浮點數二進位制透過”乘2取整“的方法來計算。以題目中0。9為例來說明:
0。9x2=1。8 取整1,小數部分是0。8
0。8x2=1。6 取整1,小數部分是0。6
0。6x2=1。2 取整1,小數部分是0。2
0。2x2=0。4 取整0,小數部分是0。4
0。4x2=0。8 取整0,小數部分是0。8
0。2x8=1。6 取整1,小數部分是0。6
以下開始迴圈
0。6x2=1。2 取整1,小數部分是0。2
0。2x2=0。4 取整0,小數部分是0。4
0。4x2=0。8 取整0,小數部分是0。8
所以,0。9的二進位制表示為 0。111001 1001 … 1001無限迴圈
所以,二進位制無法精確的表示0。9,只能近似的表示。
我們將該二進位制轉化成十進位制是 :
0。1110011001 0。8994140625
0。11100110011001 0。89996337890625
0。11100110011001 0。8999977111816406
題目解答
我們再回到題目:1。0f-0。9f ,並不等0。1f,而是近似的等於 0。1000033
0。8轉化成二進位制為:0。110011001100110011001。。。1001無限迴圈。
所以0。8近似表示為:0。7999992370605469
0。9f-0。8f 近似等於 0。10000054。
所以二者並不相等
計算機中浮點數的表示
float型別在計算機中佔用32位
其中符號位1位,階碼8位,尾數23位
比如0。9
在計算機中存放為:111111011001100110011001100110
符號:第1位:0表示正數,1表示負數;
階碼:第2-9位:11111011
尾數:第10-32位:0011 0011 0011 0011 0011 0
double型別在計算機中佔64位
其中1位符號位,階碼11位,尾數52位
比如0。9
在計算機中存放為:11111111101100110011001100110011001100110011001100110011001101
符號:第1位:0表示正數,1表示負數;
階碼:第2-12位:11111111011
尾數:第13-64位:00110011001100110011001100110011001100110011001101
總結
二進位制不能精確的表示浮點數,所以浮點數不能進行相等的比較。在涉及到金額計算的時候,建議使用BigDecimal,防止由於精度丟失帶來的BUG。