这个异常是bigdecimal的“安全锁”,强制要求除法时明确指定小数位数和舍入方式;因其设计目标是精确而非近似,遇无限循环小数(如1÷3)若不指定舍入模式便抛出arithmeticexception。

这个异常直白地说,就是BigDecimal在说:“你让我算一个除不尽的数,又不告诉我怎么取舍,我没法给你一个确定的结果。”
为什么非要指定舍入模式?
BigDecimal的设计目标是“精确”,不是“大概”。它内部用整数 × 10⁻ˢᶜᵃˡᵉ 的方式表示小数,天生拒绝模糊处理。
- 像 1 ÷ 3 这种运算,数学上是无限循环小数 0.333…,无法用有限位数完整表达
- 如果不指定舍入方式,JVM 就无法判断该截断、进一、还是四舍五入
- 为避免隐式丢失精度,它选择抛出 ArithmeticException: Non-terminating decimal expansion,而不是偷偷帮你四舍五入
和普通数值类型对比就清楚了
double 或 float 遇到 1/3 会直接返回近似值(比如 0.3333333333333333),但那是牺牲精度换来的“安静”;BigDecimal 则宁可报错,也不妥协。
- double:默许误差,适合科学估算
- BigDecimal:拒绝歧义,专为金融、账务等零容错场景设计
不指定舍入模式的代码一定报错吗?
不一定——仅当结果是无限小数时才触发。如果刚好能除尽,比如 BigDecimal.valueOf(6).divide(BigDecimal.valueOf(2)),无参调用也能成功。
- 但业务逻辑不能依赖“刚好除尽”,必须按最坏情况(如 10 元分 3 人)来写
- 一旦上线后遇到某笔金额导致无限循环,系统就会在运行时崩掉
一句话总结
这个异常不是Bug,是BigDecimal的“安全锁”:它强制你在做除法前,明确回答两个问题——“我要保留几位小数?”和“遇到5该怎么处理?”











