BigDecimal异常【Java】

    科技2024-03-31  94

    介绍

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。

    ​ BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

    异常

    异常信息

    Exception in thread “main” java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

    这个异常是我在实习期间发现的一个bug,但是需要计算金额,一般计算金额都用BigDecimal 可以防止丢精度,但是在除法的时候报错了,原因是因为BigDecimal的divide方法进行除法时当不整除,出现无限循环小数时,就会抛异常,解决方法是:使用 divide(xxxxx,y, z),设置小数点和舍入规则

    /** * 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(BigDecimal divisor, int scale, int roundingMode) scale 表示保留的位数roundingMode 表示舍入规则 ROUND_UP:进位制:不管保留数字后面是大是小(0除外)都会进1ROUND_DOWN:保留设置数字,后面所有直接去除ROUND_HALF_UP:根据保留数字后一位>=5进行四舍五入ROUND_HALF_DOWN:根据保留数字后一位>5进行四舍五入

    结果

    Processed: 0.022, SQL: 8