使用BigDecimal计算leaseRate时出现非终止小数展开错误,配置MathContext仍未解决
问题:BigDecimal计算leaseRate时抛出Non-terminating decimal expansion错误
尝试计算BigDecimal类型的leaseRate时,遇到错误:
Non-terminating decimal expansion; no exact representable decimal result
已知这是舍入问题,尝试通过MathContext precision = new MathContext(2);解决,但问题依然存在。复现代码如下:
public class Test { public static void main(String[] args) { MathContext precision = new MathContext(2); int mileage = 10; int duration = 20; BigDecimal price = new BigDecimal("34234.34",precision); double interestRate = 4.57; BigDecimal bMileage = new BigDecimal(mileage, precision); BigDecimal bDuration = new BigDecimal(duration,precision); BigDecimal bInterestRate = new BigDecimal(interestRate,precision); BigDecimal leaseRate = ((((bMileage.divide( new BigDecimal(12,precision))).multiply(bDuration)).divide( price)).add( ((bInterestRate.divide(new BigDecimal(100,precision))).multiply( price)).divide(new BigDecimal(12,precision)))); System.out.println(leaseRate); } }
问题分析与解决
核心问题:divide方法未指定舍入策略
你创建BigDecimal时使用了MathContext,但**divide方法如果只传入除数参数,默认会采用ROUND_UNNECESSARY舍入模式**——这种模式要求除法必须能精确得到结果,否则直接抛出你遇到的错误。MathContext仅在BigDecimal构造或部分运算时生效,不会自动覆盖divide的默认舍入规则。
其他潜在问题
- double转BigDecimal的精度损失:用
new BigDecimal(interestRate, precision)将double类型的4.57转为BigDecimal时,由于double是浮点数,实际存储的值可能并非精确的4.57,建议改用字符串构造:new BigDecimal("4.57", precision)。 - 分步计算的舍入累积:虽然设置了MathContext,但分步计算中的多次舍入会导致结果精度偏差,建议在除法步骤统一控制舍入逻辑。
修正后的代码示例
public class Test { public static void main(String[] args) { MathContext precision = new MathContext(2); // 改用字符串构造interestRate的BigDecimal,避免浮点数精度损失 BigDecimal bInterestRate = new BigDecimal("4.57", precision); int mileage = 10; int duration = 20; BigDecimal price = new BigDecimal("34234.34", precision); BigDecimal bMileage = new BigDecimal(mileage, precision); BigDecimal bDuration = new BigDecimal(duration, precision); // 所有divide方法都传入MathContext,指定精度和舍入规则 BigDecimal leaseRate = bMileage.divide(new BigDecimal(12), precision) .multiply(bDuration) .divide(price, precision) .add( bInterestRate.divide(new BigDecimal(100), precision) .multiply(price) .divide(new BigDecimal(12), precision) ); System.out.println(leaseRate); } }
内容的提问来源于stack exchange,提问作者jennifer ruurs
相关产品推荐
相关产品推荐

