BigDecimal的除运算,主要有下面3个重载:
- BigDecimal divide(BigDecimal divisor)
- BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode)
- BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
关于orderAmt.divide(divisor).setScale(2, roundingMode)
与 orderAmt.divide(divisor, 2, roundingMode)
,这两个表达式的核心区别在于 是否在除法操作时明确指定精度和舍入模式,以及可能引发的行为差异。
一. 表达式1:orderAmt.divide(divisor).setScale(2, roundingMode)
- 执行过程:
- 先调用
divide(BigDecimal divisor)
进行除法运算,未指定精度(scale)和舍入模式,此时会使用 默认舍入模式(BigDecimal.ROUND_UNNECESSARY
)。 - 如果除法结果无法精确表示(例如除不尽),
divide()
会直接抛出ArithmeticException
(因为默认模式要求结果必须精确)。
异常stacktrace:
java.lang.ArithmeticException:
Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1707)
- 若未抛出异常,再通过
setScale(2, roundingMode)
对结果进行精度调整,使用指定的roundingMode
舍入到 2 位小数。
- 风险:
若除法结果不精确(如1 ÷ 3
),第一步divide()
会直接报错,无法进入setScale
步骤。
二. 表达式2:orderAmt.divide(divisor, 2, roundingMode)
-
执行过程:
直接调用divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
三参数重载方法,在除法运算的同时指定精度(2位小数)和舍入模式。- 无论除法结果是否精确,都会按照指定的
scale
和roundingMode
进行舍入,不会抛出异常(除非除数为 0)。
- 无论除法结果是否精确,都会按照指定的
-
优势:
一步完成除法和舍入,避免因默认舍入模式导致的异常,且逻辑更清晰(明确告知“除法后保留2位小数,按指定方式舍入”)。
三. 核心区别总结
对比项 | 表达式1(先除后设精度) | 表达式2(除法时指定精度和舍入) |
---|---|---|
舍入时机 | 先除法(默认模式),再单独舍入 | 除法过程中直接按指定精度和模式舍入 |
异常风险 | 若除法结果不精确,第一步就会报错 | 不会报错(除数非0时),强制按规则舍入 |
代码意图 | 不明确(未显式声明精度要求) | 清晰(明确“保留2位小数,按XX方式舍入”) |
推荐程度 | 不推荐(存在隐藏异常风险) | 推荐(安全、语义明确) |
四. 最佳实践
永远使用 三参数的 divide
方法(表达式2),显式指定精度和舍入模式,避免依赖默认行为(默认模式 ROUND_UNNECESSARY
几乎不会在实际业务中使用,因为大部分除法运算结果都不精确)。
例如:
BigDecimal result = orderAmt.divide(
BigDecimal.ONE.subtract(feeRatio), // 除数
2, // 保留2位小数
RoundingMode.HALF_UP // 舍入模式(根据业务需求选择)
);
这样既保证了代码的健壮性,又让可读性更强(一看就知道是“保留2位小数的除法”)。
常见舍入模式:
- RoundingMode.HALF_UP:四舍五入(最常用)。
- RoundingMode.DOWN:直接截断,不进位。
- RoundingMode.UP:无论尾数是否为 0,都进位(例如 0.333 保留 2 位为 0.34)。
来源链接:https://www.cnblogs.com/buguge/p/18844473
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容