问题
简单记录下在使用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