Java浮點類型精度問題
public static void main(String[] args) throws Exception {
float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
System.out.println(a == b);//false
Float c = a;
Float d = b;
System.out.println(c.equals(d));//false
System.out.println(a);//0.100000024
System.out.println(b);//0.099999964
}
public static void main(String[] args) throws Exception {
double a = 1.0 - 0.9;
double b = 0.9 - 0.8;
System.out.println(a == b);//true
Double c = a;
Double d = b;
System.out.println(c.equals(d));//true
System.out.println(a);//0.09999999999999998
System.out.println(b);//0.09999999999999998
}
“浮點數之間的等值判斷,基本數據類型不能用 == 來比較,包裝數據類型不能用equals來判斷。”
—— 《Java開發手冊》
浮點數值不適用於無法接收舍入誤差的計算中。這種舍入誤差的主要原因是浮點數採用二進制系統表示,而在二進制系統中無法精確地表示分數1/10,就好像十進制無法精確地表示分數1/3一樣。
解決辦法
- 指定一個誤差範圍,兩個浮點數的差值在此範圍之內,才認爲是相等的。
public static void main(String[] args) throws Exception {
float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
float diff = 1e-6f;
//absolute value
System.out.println(Math.abs(a - b) < diff);//true
}
- 使用BigDecimal 來定義值,再進行浮點數的運算操作。
public static void main(String[] args) throws Exception {
BigDecimal a = BigDecimal.valueOf(1.0);
BigDecimal b = BigDecimal.valueOf(0.9);
BigDecimal c = BigDecimal.valueOf(0.8);
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
System.out.println(x.equals(y));//true
System.out.println(x);//0.1
System.out.println(y);//0.1
}