Java BigDecimal 使用完全指南
📗 开发笔记· 2026-10-02 18:22 · 5

Java BigDecimal 使用完全指南

Java 的 double、float 存在浮点精度丢失,不适合金额、账务等高精度计算。`BigDecimal` 用于实现任意精度的小数运算。本文包含对象创建、四则运算、取余、格式化、开发注意事项,适合开发和面试复习。

目录

1. 什么是 BigDecimal

java.math.BigDecimal 用来做高精度数值计算,解决 double/float 二进制浮点精度丢失问题。

重要特性:BigDecimal 是不可变类,加减乘除不会修改原对象,运算结果必须接收返回的新对象。

2. 创建 BigDecimal 对象

2.1 几种构造方式

java 复制代码
// ✅ 推荐:字符串构造,无精度丢失
BigDecimal num1 = new BigDecimal("10.5");

// ❌ 不推荐:直接传入 double,会带入浮点误差
BigDecimal num2 = new BigDecimal(10.5);

// ✅ 整数入参,安全
BigDecimal num3 = new BigDecimal(10);

// 由 BigInteger 转换
BigInteger bigInt = new BigInteger("123456789");
BigDecimal num4 = new BigDecimal(bigInt);

// ✅ 推荐:valueOf,内部会处理 double 精度问题
BigDecimal num5 = BigDecimal.valueOf(10.5);

2.2 开发建议

  1. 小数优先使用字符串构造或 BigDecimal.valueOf(double);
  2. 尽量避免 new BigDecimal(doubleVal),容易出现意料之外的精度。

3. 数值运算

方法 说明
add 加法
subtract 减法
multiply 乘法
divide 除法,必须指定精度和舍入模式
remainder 取余数

注意:除法如果遇到无限小数,不指定精度会直接抛 ArithmeticException。

3.1 加法 add

java 复制代码
BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("20");
BigDecimal sum = a.add(b);
// sum = 30

3.2 减法 subtract

java 复制代码
BigDecimal a = new BigDecimal("20");
BigDecimal b = new BigDecimal("10");
BigDecimal sub = a.subtract(b);
// sub = 10

3.3 乘法 multiply

java 复制代码
BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("2");
BigDecimal mul = a.multiply(b);
// mul = 20

3.4 除法 divide(重点)

参数:divide(除数, 保留小数位数, 舍入模式)
RoundingMode.HALF_UP:四舍五入,业务最常用。

java 复制代码
BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");
// 保留2位小数,四舍五入
BigDecimal div = a.divide(b, 2, RoundingMode.HALF_UP);
// div = 3.33

3.5 取余 remainder

java 复制代码
BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");
BigDecimal rem = a.remainder(b);
// rem = 1

4. BigDecimal 格式化输出

使用 NumberFormat 实现普通数字、货币、百分比格式化。

常用API:

  • NumberFormat.getInstance():普通数字格式
  • NumberFormat.getCurrencyInstance():货币格式
  • NumberFormat.getPercentInstance():百分比格式
  • setMaximumFractionDigits(n):最大小数位
  • setMinimumFractionDigits(n):最小小数位
  • setGroupingUsed(true):开启千分位分隔
  • format(obj):转为格式化字符串

示例代码:

java 复制代码
import java.math.BigDecimal;
import java.text.NumberFormat;

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal num = new BigDecimal("1234567.890");

        // 普通数字格式化,带千分位
        NumberFormat numFormat = NumberFormat.getInstance();
        numFormat.setMaximumFractionDigits(2);
        String numStr = numFormat.format(num);
        System.out.println("普通格式:" + numStr);

        // 货币格式
        NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
        String currencyStr = currencyFormat.format(num);
        System.out.println("货币格式:" + currencyStr);

        // 百分比格式
        NumberFormat percentFormat = NumberFormat.getPercentInstance();
        String percentStr = percentFormat.format(num);
        System.out.println("百分比格式:" + percentStr);
    }
}

输出示例:

复制代码
普通格式:1,234,567.89
货币格式:¥1,234,567.89
百分比格式:123456789%

5. 开发注意事项

  1. BigDecimal 不可变,运算后必须接收返回值,原对象不会改变;
  2. 创建对象尽量用字符串或 valueOf(),不要直接 new BigDecimal(double);
  3. 除法务必指定小数位数与舍入模式,防止无限小数抛出异常;
  4. 金额比较不要用 equals(),优先使用 compareTo();
  5. 业务上金额计算统一约定小数位数与舍入规则。

6. 小结

  • 金额、高精度计算场景必须使用 BigDecimal,拒绝 double/float;
  • 创建对象:字符串 / valueOf 优先;
  • 运算:加减乘直接调用方法,除法必须带精度和舍入模式;
  • 展示:借助 NumberFormat 快速实现千分位、货币、百分比格式化。