Scala除法运算与取整问题求助:如何让结果保留两位小数?
解决Scala中BigDecimal除法的小数位控制问题
首先,咱们来拆解一下你遇到的两个核心问题:
第一个异常的根源
你最初的代码抛出java.lang.ArithmeticException: Non-terminating decimal expansion,本质原因是BigDecimal在除法运算时,若结果是无限循环小数,默认不会自动执行舍入操作——它要求必须明确指定舍入规则,否则就会抛出这个异常,以此避免隐式的精度丢失。
为什么转Double的方案达不到预期?
你改成转Double后再做除法,结果出现一堆冗余小数位,问题出在两点:
- Double是浮点数,本身精度有限,把BigDecimal转成Double的过程就可能已经丢失了精确性;
- Double的除法运算结果也是浮点数,无法精确控制小数位数,自然会出现多余的小数位,而且这种方式也达不到你想要的精确舍入效果。
正确的解决方案:全程用BigDecimal处理
要实现除法结果仅保留两位小数,你应该在BigDecimal的运算阶段就指定舍入规则,全程避免转成Double。有两种简洁且严谨的写法:
写法一:先除法再设置小数位
val ratio = (order.price.toBigDecimal / order.subPrice.toBigDecimal) .setScale(2, BigDecimal.RoundingMode.HALF_UP) .toString
写法二:除法时直接指定精度(更直观)
val ratio = order.price.toBigDecimal.divide( order.subPrice.toBigDecimal, 2, BigDecimal.RoundingMode.HALF_UP ).toString
这两种写法的效果完全一致:
- 全程用BigDecimal运算,保证数值精度不丢失;
- 通过
setScale或divide的参数明确指定保留2位小数,采用四舍五入(HALF_UP)的舍入模式; - 最终转成字符串后就是你想要的两位小数格式,比如
9.84而不是一堆冗余的小数位。
额外补充:如果需要取整
要是你的需求是得到整数结果(比如把9.84变成10或9),只需要把setScale的第一个参数改成0即可:
val integerResult = (order.price.toBigDecimal / order.subPrice.toBigDecimal) .setScale(0, BigDecimal.RoundingMode.HALF_UP) .toString
内容的提问来源于stack exchange,提问作者Jwan622
相关产品推荐
相关产品推荐

