BigDecimal运算核心是创建用字符串、除法必设scale和舍入模式;禁用double构造,加减乘需显式赋值,比较用compareTo()。

用BigDecimal做加减乘除,核心就两条:创建别错、除法别漏。精度丢失和舍入异常,八成出在这两个环节。
创建时别用double,字符串最稳
0.1在二进制里是无限循环小数,double存它本身就有误差。用new BigDecimal(0.1)等于把误差直接“固化”进对象里,后面再怎么算都救不回来。
- ✅ 推荐:用字符串构造,
new BigDecimal("0.1"),原样保留,零误差 - ✅ 次选:用
BigDecimal.valueOf(0.1),内部做了toString兜底,比直接传double安全 - ❌ 禁止:
new BigDecimal(0.1)或new BigDecimal(1.23)这类double入参
加减乘相对安全,但别链式调用
add、subtract、multiply这些方法返回新对象,本身不改变原值。问题常出在连续调用没保存中间结果,比如a.add(b).multiply(c),如果b或c精度高,中间结果可能被隐式截断。
- 建议每步运算后显式赋值,便于调试和控制scale
- 加减法默认保留最多小数位(如
"1.23".add("1.2")得"2.43"),无需额外设精度 - 乘法结果的小数位数 = 两操作数小数位数之和,注意是否超出业务要求(比如金额通常只到分)
除法必须三要素齐备
divide()不指定参数会直接抛ArithmeticException,因为10÷3这种无限循环小数,BigDecimal拒绝擅自决定怎么截——这是保护,不是bug。
- 必须指定目标小数位数(scale),例如
2表示保留两位小数 - 必须指定舍入模式,常用
RoundingMode.HALF_UP(四舍五入) - 除数不能为零,建议提前判空或捕获
ArithmeticException - 示例:
a.divide(b, 2, RoundingMode.HALF_UP)
比较和等值判断别踩坑
金额比较不用==或equals(),它们要么比引用,要么连精度一起比(new BigDecimal("1.0").equals(new BigDecimal("1.00"))返回false)。
- ✅ 等值判断统一用
compareTo(),只比数值大小,0表示相等 - ✅ 比较大小也用
compareTo(),返回负数、0、正数分别代表小于、等于、大于 - ⚠️ 注意
setScale()会重新生成对象,若需保留原精度再比较,先调用再比

















