BigDecimal不会出现0.1+0.2≠0.3的问题,因其基于十进制精确运算,用BigInteger存整数、scale存小数位,避免二进制浮点误差;构造须用字符串,运算须调用add等方法,比较用compareTo而非equals。

BigDecimal 为什么不会出现 0.1 + 0.2 ≠ 0.3 的问题
因为 double 和 float 是二进制浮点数,无法精确表示十进制小数(如 0.1),导致计算结果存在舍入误差。而 BigDecimal 内部用 BigInteger 存整数部分、scale 存小数位数,所有运算都在十进制下进行,能严格保留精度。
常见错误现象:
System.out.println(0.1 + 0.2); // 输出 0.30000000000000004这种问题在金额场景里不可接受——哪怕只是展示,用户看到
¥19.999999999999996 也会质疑系统可靠性。
构造 BigDecimal 时必须用字符串,不能用 double
用 double 构造会把原始浮点误差直接带进去,等于还没开始算就错了:
-
new BigDecimal(0.1)→ 实际是0.1000000000000000055511151231257827021181583404541015625 -
new BigDecimal("0.1")→ 精确就是0.1
所有金额输入(包括用户提交的字符串、数据库查出的数值字段)都应第一时间转成 BigDecimal("..."),避免中间经过 double。
立即学习“Java免费学习笔记(深入)”;
加减乘除必须用方法调用,不能用运算符
Java 不支持 +、- 等操作符重载,所以 bigA + bigB 语法根本不存在。必须显式调用:
- 加法:
bigA.add(bigB) - 减法:
bigA.subtract(bigB) - 乘法:
bigA.multiply(bigB) - 除法:
bigA.divide(bigB, scale, roundingMode)—— 除法必须指定小数位数和舍入方式,否则遇到无限循环小数(如1/3)直接抛ArithmeticException
常见错误:忘记传 RoundingMode.HALF_UP,默认用的是 RoundingMode.UNNECESSARY,只要结果不能精确表示就崩溃。
equals() 不能用于比较大小,compareTo() 才是正确姿势
BigDecimal.equals() 同时比较值和精度(scale),new BigDecimal("1.0").equals(new BigDecimal("1.00")) 返回 false。金额比大小、判相等,一律用:
- 判相等:
a.compareTo(b) == 0 - 比大小:
a.compareTo(b) > 0表示 a > b - 注意:
compareTo()不会因 scale 不同而误判,它只看实际数值
数据库字段如果是 DECIMAL(10,2),查出来可能带两位小数;用户输入可能是 "100",scale=0。混用时 equals() 很容易静默失败。
最常被忽略的一点:BigDecimal 是不可变对象,所有运算都返回新实例。写 amount.add(tax) 而不赋值给变量,等于什么都没改。










