【Java面經整理】爲什麼會出現4.0-3.6=0.40000001這種現象?

ps:Java面試題整理專欄,專門收集整理搬運面試題和答案

這種舍入誤差的主要原因是:
浮點數值採用二進制系統表示, 而在二進制系統中無法精確地表示分數 1/10。
這 就好像十進制無法精確地表示分數 1/3—樣。
如果在數值計算中不允許有任何舍入誤差, 就應該使用 BigDecimal類。

浮點數值不適用於無法接受舍入誤差的金融計算中。
例如,命令 System.out.println ( 2.0-1.1 ) 將打印出 0.8999999999999999, 而不是人們想象的 0.9。

爲什麼二進制無法精確表示1/10

其實跟數位表示法有關,比如十進制的情況下:
123,相當於
1*10^2+2*10^1+3*10^0(值*進制^位置,個位0,十位1,百位2)
同理:1/10由二進制表示小數的時候只能夠表示能夠用1/(2^n)

例如:
0.5能夠表示,因爲它可以表示成爲1/2
0.75也能夠表示,因爲它可以表示成爲
1/2+1/(2^2)
0.875也能夠表示,因爲它可以表示成爲1/2+1/(2^2)+1/(2^3)
0.9375也能夠表示,因爲它可以表示成爲1/2+1/(2^2)+1/(2^3)+1/(2^4)
但是0.1不能夠精確表示,因爲它不能表示成爲1/(2^n)的和的形式


擴展:

大數值

如果基本的整數和浮點數精度不能夠滿足需求, 那麼可以使用java.math 包中的兩個 很有用的類:Biglnteger 和 BigDecimal 這兩個類可以處理包含任意長度數字序列的數值。 Biglnteger類實現了任意精度的整數運算, BigDecimal 實現了任意精度的浮點數運算。

使用靜態的 valueOf方法可以將普通的數值轉換爲大數值:

Biglnteger a = Biglnteger.valueOf(100); 

遺憾的是,不能使用人們熟悉的算術運算符(如:+ 和 *) 處理大數值。
而需要使用大數 值類中的 add 和 multiply 方法。

Biglnteger c = a.add(b); // c = a + b 
Biglnteger d = c.nultipiy(b.add(Biglnteger.valueOf(2))); // d = c * (b + 2)

註釋:

與 C++ 不同, Java 沒有提供運算符重載功能。程序員無法重定義 + 和 * 運算 符, 使其應用於
BigInteger 類的 add 和 multiply 運算。Java 語言的設計者確實爲字符串的連接重載了 + 運算符,但沒有重載其他的運算符,也沒有給 Java 程序員在自己的類中重載運算符的機會

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章