關於Java中2.0-1.1!=0.9的問題
問題引出:
在《Java核心技術》中關於浮點數值計算部分提到,System.out.println(2.0-1.1)
這條語句並不是想當然的0.9
,而是0.8999999999999999
,倒也不是很驚訝,我知道大概的原因是:浮點數值用二進制的形式來表現,從而造成了一部分位數丟失。但是,具體細節我其實並不知道,所以花了一些時間,翻閱了一些前輩大牛寫的文章,有了一定的認識,特此記錄以下。
我還做了以下嘗試:
System.out.println(0.01f+0.04f);//輸出0.049999997
System.out.println(0.01f+0.04);//輸出0.04999999977648258
System.out.println(2.0-1.1);//輸出0.8999999999999999
System.out.println(2.0f-1.1f);//輸出0.9
System.out.println(2.0-0.1);//輸出1.9
一些總結:
- 整數和小數轉換成二進制數,機制不同。整數除二取余,直到為1為之,一定不會無限循環,所以能夠精確用二進制表示。但小數不同,小數部分乘以2,取整數部分,再把小數部分乘以2...直到小數部分為0為止,是有一定幾率無限循環下去的。
- Java中會將未聲明類型的小數默認當做double型處理,也就是語句3的情況。而語句4聲明數值類型為float時,因為本身存在精度上的丟失,反而輸出了0.9。
- 語句1和語句2輸出差異在於0.01f在精度上的差異,具體可以參考鏈接:[解惑]剖析float型的內存存儲和精度丟失問題
- 那么語句5同樣是兩個double類型相加,為什么輸出又是“正確”的呢,參考:為什么在java中 2.0-1.1=0.899999... 但是2.0-0.1卻可以=1.9?中的回答。