| 方法 | 代碼 | 輸出示例 | 特點 |
|---|---|---|---|
| BigDecimal.setScale | new BigDecimal(v).setScale(2, RoundingMode.HALF_UP).doubleValue() | 111231.56 | 精確控制捨入模式,適合金融計算 |
| DecimalFormat | new DecimalFormat("#.00").format(v) | 111231.56 | 模式靈活,支援分組分隔符、前綴後綴 |
| String.format | String.format("%.2f", v) | 111231.56 | 最簡潔,適合日誌、拼接字符串 |
| NumberFormat | NumberFormat.getInstance().setMaximumFractionDigits(2); nf.format(v) | 111,231.56 | 區域化敏感,自動加千分位分隔符 |
RoundingMode.HALF_UP:四捨五入 (最常用)。RoundingMode.HALF_EVEN:銀行家捨入法,減少統計偏差。RoundingMode.DOWN:截斷 (向零方向)。RoundingMode.CEILING/FLOOR:向正/負無窮大方向。
System.out.println(0.1 + 0.2); // 0.30000000000000004 ❌
System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.2"))); // 0.3 ✅
鐵律:涉及金額、精度敏感計算,全程使用 BigDecimal,構造器務必傳 String,禁用 double 构造器。
public final class MathUtil {
private static final int DEF_DIV_SCALE = 10;
private MathUtil() {}
public static double add(double v1, double v2) {
return new BigDecimal(Double.toString(v1)).add(new BigDecimal(Double.toString(v2))).doubleValue();
}
public static String add(String v1, String v2) {
return new BigDecimal(v1).add(new BigDecimal(v2)).toString();
}
public static double subtract(double v1, double v2) { /* 同理 */ }
public static double multiply(double v1, double v2) { /* 同理 */ }
public static double divide(double v1, double v2) {
return divide(v1, v2, DEF_DIV_SCALE);
}
public static double divide(double v1, double v2, int scale) {
return divide(v1, v2, scale, RoundingMode.HALF_EVEN);
}
public static double divide(double v1, double v2, int scale, RoundingMode mode) {
if (scale < 0) throw new IllegalArgumentException("scale must >= 0");
return new BigDecimal(Double.toString(v1))
.divide(new BigDecimal(Double.toString(v2)), scale, mode).doubleValue();
}
public static double round(double v, int scale) {
return round(v, scale, RoundingMode.HALF_EVEN);
}
public static double round(double v, int scale, RoundingMode mode) {
if (scale < 0) throw new IllegalArgumentException("scale must >= 0");
return new BigDecimal(Double.toString(v)).setScale(scale, mode).doubleValue();
}
}
String.format("%.2f", amount) 或 DecimalFormat。MathUtil,參數傳 String 或 double (工具類內部轉 String)。DECIMAL(19,4),JPA 用 @Column(precision=19, scale=4) BigDecimal。decimal.js 或後端格式化為 String 返回。「展示用 format,計算用 BigDecimal,存儲用 DECIMAL」三板斧解決 99% 精度問題。掌握四種格式化輸出差異,根據場景(日誌、報表、國際化、金融)選擇最合適的一種。