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

Java BigDecimal 高精度計算完全指南:格式化、四捨五入與精確加減乘除工具類

     編輯:Java 綜合教學

Java BigDecimal 高精度計算完全指南:格式化、四捨五入與精確加減乘除工具類

Java BigDecimal 高精度計算完全指南:格式化、四捨五入與精確加減乘除工具類

Java float/double 二進制浮點數無法精確表示十進制小數(如 0.1),財務、電商等場景必須使用 BigDecimal。本文總結格式化輸出、四捨五入模式、精確算術封裝及常用工具方法。

一、保留兩位小數的多種方式

double d = 3.1415926;
// 1. DecimalFormat
String s1 = new DecimalFormat("0.00").format(d);        // "3.14"
String s2 = new DecimalFormat("#.00").format(d);        // "3.14"
// 2. String.format
String s3 = String.format("%.2f", d);                   // "3.14"
// 3. BigDecimal 四捨五入
BigDecimal bd = new BigDecimal(d);
double rounded = bd.setScale(2, RoundingMode.HALF_UP).doubleValue(); // 3.14

二、精確算術工具類 PreciseCompute

public class PreciseCompute {
    private static final int DEF_DIV_SCALE = 10;

    public static double add(double v1, double v2) {
        return new BigDecimal(Double.toString(v1)).add(new BigDecimal(Double.toString(v2))).doubleValue();
    }
    public static double sub(double v1, double v2) {
        return new BigDecimal(Double.toString(v1)).subtract(new BigDecimal(Double.toString(v2))).doubleValue();
    }
    public static double mul(double v1, double v2) {
        return new BigDecimal(Double.toString(v1)).multiply(new BigDecimal(Double.toString(v2))).doubleValue();
    }
    public static double div(double v1, double v2) { return div(v1, v2, DEF_DIV_SCALE); }
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) throw new IllegalArgumentException("Scale must be >= 0");
        return new BigDecimal(Double.toString(v1)).divide(new BigDecimal(Double.toString(v2)), scale, RoundingMode.HALF_UP).doubleValue();
    }
    public static double round(double v, int scale) {
        if (scale < 0) throw new IllegalArgumentException("Scale must be >= 0");
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
    }
}

關鍵點:構造器傳 Double.toString(v) 而非直接 v,避免二進制誤差帶入;除法指定精度與舍入模式。

三、帶千分位格式化並保留兩位小數

private BigDecimal toBigDecimal(Object obj) {
    String val = String.valueOf(obj).replaceAll(",", "");
    if (!isNumber(val)) return BigDecimal.ZERO;
    return new BigDecimal(val).setScale(2, RoundingMode.HALF_UP);
}

private String formatWithComma(Object obj) {
    BigDecimal bd = toBigDecimal(obj);
    DecimalFormat df = new DecimalFormat("#,###.00");
    String s = df.format(bd);
    return s.startsWith(".") ? "0" + s : s; // 處理 .00 -> 0.00
}

private boolean isNumber(String s) {
    try { Double.parseDouble(s); return true; } catch (NumberFormatException e) { return false; }
}

四、RoundingMode 常用枚舉

五、最佳實踐建議

  • 財務金額全程使用 BigDecimal,禁止 double 參與計算。
  • 數據庫存儲用 DECIMAL(19,4) 或更高精度。
  • 構造器優先用 String 或 valueOf,避免 new BigDecimal(double)。
  • 除法必須指定 scale 與 RoundingMode,否則不盡除數拋異常。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
模式行為示例 (1.555 -> 2位)
HALF_UP四捨五入1.56
HALF_DOWN五捨六入1.55
HALF_EVEN銀行家算法(向偶數靠攏)1.56
UP遠離零方向1.56
DOWN趨向零方向1.55
CEILING向正無窮1.56
FLOOR向負無窮1.55