首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 保留兩位小數 4 種姿勢與高精度計算工具類

     編輯:Java 相關知識

四種格式化輸出方式

方法代碼輸出示例特點
BigDecimal.setScalenew BigDecimal(v).setScale(2, RoundingMode.HALF_UP).doubleValue()111231.56精確控制捨入模式,適合金融計算
DecimalFormatnew DecimalFormat("#.00").format(v)111231.56模式靈活,支援分組分隔符、前綴後綴
String.formatString.format("%.2f", v)111231.56最簡潔,適合日誌、拼接字符串
NumberFormatNumberFormat.getInstance().setMaximumFractionDigits(2); nf.format(v)111,231.56區域化敏感,自動加千分位分隔符

捨入模式選擇指南

  • RoundingMode.HALF_UP:四捨五入 (最常用)。
  • RoundingMode.HALF_EVEN:銀行家捨入法,減少統計偏差。
  • RoundingMode.DOWN:截斷 (向零方向)。
  • RoundingMode.CEILING/FLOOR:向正/負無窮大方向。

浮點數運算陷阱與 BigDecimal 解決方案


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();
    }
}

使用建議

  1. **展示層**格式化:String.format("%.2f", amount) 或 DecimalFormat。
  2. **業務層**計算:統一調用 MathUtil,參數傳 String 或 double (工具類內部轉 String)。
  3. **持久層**存儲:MySQL 用 DECIMAL(19,4),JPA 用 @Column(precision=19, scale=4) BigDecimal。
  4. **序列化**傳輸:JSON 直接傳 BigDecimal (Jackson 自動處理),前端用 decimal.js 或後端格式化為 String 返回。

總結

「展示用 format,計算用 BigDecimal,存儲用 DECIMAL」三板斧解決 99% 精度問題。掌握四種格式化輸出差異,根據場景(日誌、報表、國際化、金融)選擇最合適的一種。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved