【Java 每日一題】浮點數運算陷阱:10.00 - 9.60 ≠ 0.4
public class Ques1212 {
public static void main(String[] args) {
System.out.println(10.00 - 9.60);
}
}
輸出結果
0.40000000000000036
根因:IEEE 754 雙精度浮點數表示局限
- 十進制
0.1、0.6 等在二進制中無法精確表示,屬於無限循環小數。
double(64 位)只能存儲近似值,運算時誤差累積。
10.00 和 9.60 都無法精確存儲,相減放大了誤差。
正確處理方案
方案一:BigDecimal(金融/精確計算必用)
BigDecimal a = new BigDecimal("10.00");
BigDecimal b = new BigDecimal("9.60");
System.out.println(a.subtract(b)); // 0.40
構造器必須傳字符串,不可傳 double,否則將近似值帶入。
方案二:整數縮放(性能敏感場景)
long a = 1000; // 10.00 * 100
long b = 960; // 9.60 * 100
System.out.println((a - b) / 100.0); // 0.4
方案三:格式化輸出(僅展示層)
System.out.printf("%.2f%n", 10.00 - 9.60); // 0.40
避坑清單
- 禁止用
== 比較浮點數,使用 Math.abs(a - b) < epsilon。
- 涉及金額、精度要求高的業務全鏈路使用 BigDecimal(資料庫用 DECIMAL,Java 用 BigDecimal,前端傳字符串)。
- JSON 序列化時配置
writeNumbersAsStrings=true 避免精度丟失。