记录一次异常:Non-terminating decimal expansion; no exact representable decimal result
代码:
final BigDecimal bigDecimal = new BigDecimal("10.0");
bigDecimal.divide(new BigDecimal("3.0"));
报错详细信息:
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1693)
原因是 10 除以3 除不尽 时未指定舍未位规则
当然 在可以除尽的时候 是不会报错的
新手就很容易犯错误 比如测试的时候使用除尽数字 如下:
final BigDecimal bigDecimal = new BigDecimal("10.0");
final BigDecimal divide = bigDecimal.divide(new BigDecimal("2.0"));
输出: 5
那么怎么指定舍未位规则呢 我们只需要增加 divide方法2个参数 保留小数位 和 规则 我下面使用的是 四舍五入规则
divide(new BigDecimal("3.0"), 2, RoundingMode.HALF_UP);
修改为:
final BigDecimal bigDecimal = new BigDecimal("10.0");
final BigDecimal divide = bigDecimal.divide(new BigDecimal("3.0"), 2, RoundingMode.HALF_UP);
log.info("divide:{}", divide);
输出: 3.33
简单介绍下 RoundingMode 常用规则 以保留2为小数为例
RoundingMode.CEILING:等价于(BigDecimal.ROUND_CEILING)舍入模式向正无穷大舍入。如果结果是正的,则行为与RoundingMode.UP相同;如果为负,则行为与RoundingMode.DOWN相同。请注意,此舍入模式永远不会减少计算值
RoundingMode.DOWN:等价于(BigDecimal.ROUND_DOWN)舍入模式向零舍入。从不增加丢弃分数之前的数字(即截断)。请注意,这种舍入模式永远不会增加计算值的大小 3.339 ->3.33
RoundingMode.FLOOR:等价于(BigDecimal.ROUND_FLOOR)舍入模式向负无穷大舍入。如果结果是正的,则与RoundingMode.DOWN一样;如果为负,则表现与RoundingMode.UP相同。请注意,此舍入模式永远不会增加计算值
RoundingMode.HALF_DOWN:等价于(BigDecimal.ROUND_HALF_DOWN)五舍六入,舍入模式向“最近的邻居”舍入,除非两个邻居是等距的,在这种情况下向下舍入。如果丢弃的分数 > 0.5,则行为与RoundingMode.UP相同;否则,行为与RoundingMode.DOWN相同
RoundingMode.HALF_UP:等价于(BigDecimal.ROUND_HALF_UP)四舍五入,舍入模式向“最近的邻居”舍入,除非两个邻居是等距的,在这种情况下向上舍入。如果丢弃的分数 ≥ 0.5,则行为与RoundingMode.UP相同;否则,行为与RoundingMode.DOWN相同。请注意,这是学校通常教授的舍入模式
RoundingMode.HALF_EVEN:等价于(BigDecimal.ROUND_HALF_EVEN) 这个比较绕,整数位若是奇数则四舍五入,若是偶数则五舍六入 --舍入模式向“最近的邻居”舍入,除非两个邻居是等距的,在这种情况下,向偶数邻居舍入。如果丢弃的分数左边的数字是奇数,则表现与RoundingMode.HALF_UP相同;如果是偶数,其行为与RoundingMode.HALF_DOWN相同。请注意,这是一种舍入模式,当在一系列计算中重复应用时,可在统计上最小化累积误差。它有时被称为“银行家四舍五入”,主要用于美国。这种舍入模式类似于 Java 中用于float和double算术的舍入策略