java.lang.ArithmeticException: Non-terminating decimal expansion; no exactrepresentabledecimalresult

问题

简单记录下在使用BigDecimal时碰到的异常,改异常是在使用divide这个方法时,由于除出来的结果是无限小数导致的。

解决方法

解决很简单,为divide方法设置精确的小数点,如:a.divide(b,1),保留1位小数。

divide源码

    /**
     * Returns a {@code BigDecimal} whose value is {@code (this /
     * divisor)}, and whose scale is as specified.  If rounding must
     * be performed to generate a result with the specified scale, the
     * specified rounding mode is applied.
     *
     * <p>The new {@link #divide(BigDecimal, int, RoundingMode)} method
     * should be used in preference to this legacy method.
     *
     * @param  divisor value by which this {@code BigDecimal} is to be divided.
     * @param  scale scale of the {@code BigDecimal} quotient to be returned.
     * @param  roundingMode rounding mode to apply.
     * @return {@code this / divisor}
     * @throws ArithmeticException if {@code divisor} is zero,
     *         {@code roundingMode==ROUND_UNNECESSARY} and
     *         the specified scale is insufficient to represent the result
     *         of the division exactly.
     * @throws IllegalArgumentException if {@code roundingMode} does not
     *         represent a valid rounding mode.
     * @see    #ROUND_UP
     * @see    #ROUND_DOWN
     * @see    #ROUND_CEILING
     * @see    #ROUND_FLOOR
     * @see    #ROUND_HALF_UP
     * @see    #ROUND_HALF_DOWN
     * @see    #ROUND_HALF_EVEN
     * @see    #ROUND_UNNECESSARY
     */
    public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
        if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
            throw new IllegalArgumentException("Invalid rounding mode");
        if (this.intCompact != INFLATED) {
            if ((divisor.intCompact != INFLATED)) {
                return divide(this.intCompact, this.scale, divisor.intCompact, divisor.scale, scale, roundingMode);
            } else {
                return divide(this.intCompact, this.scale, divisor.intVal, divisor.scale, scale, roundingMode);
            }
        } else {
            if ((divisor.intCompact != INFLATED)) {
                return divide(this.intVal, this.scale, divisor.intCompact, divisor.scale, scale, roundingMode);
            } else {
                return divide(this.intVal, this.scale, divisor.intVal, divisor.scale, scale, roundingMode);
            }
        }
    }

这是以前的divide方法,现在有个新的divide方法,我们先看看这个遗留方法

  • 返回一个 BigDecimal 类型的值,其值为 两者相除,其scale(scale指你要保留的小数点位数,或者叫精度)为指定的。
  • 如果必须执行舍入以生成具有指定scale(精度)的结果,则应用指定的舍入模式。 应该优先使用新的divide方法 #divide(BigDecimal, int, RoundingMode) 而不是这种遗留方法。
  • 参数 divisor 被除以的 值。
  • 参数 scale 要返回商的保留小数的位数。
  • 参数 roundingMode 要使用的舍入模式。
  • 返回值 return {@code this / divisor}
  • 异常 throws ArithmeticException 如果 {除数 divisor} 为零,{@code roundingMode==ROUND_UNNECESSARY} 并且指定的比例不足以准确表示除法的结果,会抛出算数异常。
  • 异常 throws IllegalArgumentException 如果 roundingMode 参数不是他规定的那几个舍入模式,就会抛非法参数异常(让你不听大哥的!)。
    #ROUND_UP
    #ROUND_DOWN
    #ROUND_CEILING
    #ROUND_FLOOR
    #ROUND_HALF_UP 常用的四舍五入(保留位后一位是5进位)
    #ROUND_HALF_DOWN 四舍五入(保留位后一位是5舍弃
    #ROUND_HALF_EVEN
    #ROUND_UNNECESSARY

这是新的divide方法

/**
 * Returns a {@code BigDecimal} whose value is {@code (this /
 * divisor)}, and whose scale is as specified.  If rounding must
 * be performed to generate a result with the specified scale, the
 * specified rounding mode is applied.
 *
 * @param  divisor value by which this {@code BigDecimal} is to be divided.
 * @param  scale scale of the {@code BigDecimal} quotient to be returned.
 * @param  roundingMode rounding mode to apply.
 * @return {@code this / divisor}
 * @throws ArithmeticException if {@code divisor} is zero,
 *         {@code roundingMode==RoundingMode.UNNECESSARY} and
 *         the specified scale is insufficient to represent the result
 *         of the division exactly.
 * @since 1.5
 */
public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
    return divide(divisor, scale, roundingMode.oldMode);
}

总结

源码是越点越恐怖,有兴趣的朋友可以自己去点一点,(w点点,q点点,e点点嘟嘟嘟嘟嘟嘟嘟嘟嘟嘟嘟

总结一下(说人话),divide方法,A.divide(B, 2 ,ROUND_HALF_UP)
A / B ,2 指的是保留两位小数,四舍五入,例如结果是2.366,执行后就是2.37;2.4333,执行后就是2.43

贴一个看到的有关bigdecimal的总结文章,写的蛮好的值得收藏!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值