Java 的 Bigdecimal.divide 和四舍五入

新手上路,请多包涵

在工作中,我们在试图将一个大数除以 1000 时发现了一个问题。这个数字来自数据库。

说我有这个方法:

 private static BigDecimal divideBy1000(BigDecimal dividendo) {
    if (dividendo == null) return null;

    return dividendo.divide(BigDecimal.valueOf(1000), RoundingMode.HALF_UP);
}

当我拨打以下电话时

divideBy1000(new BigDecimal("176100000"))

我收到 176100 的预期值。但是如果我尝试下面的行

divideBy1000(new BigDecimal("1761e+5"))

我收到值 200000。为什么会这样?这两个数字相同,但表示形式不同,最新的是我从数据库中收到的。我知道,不知何故,JVM 将数字 1761 除以 1000,向上舍入并在末尾填充 0。

避免这种行为的最佳方法是什么?请记住,原始号码不受我控制。

原文由 Raphael do Vale 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

正如 javadoc 中所指定的,a BigDecimal 由一个整数值和一个 scale 定义。

因此,BigDecimal 表示的数字的值为 (unscaledValue × 10^(-scale))。

所以 BigDecimal("1761e+5") 的比例为 -5 和 BigDecimal(176100000) 的比例为 0。

两个 BigDecimal 的除法分别使用 -5 和 0 比例来完成,因为在划分时没有指定比例。 divide 文档 解释了结果不同的原因。

divide

 public BigDecimal divide(BigDecimal divisor)

返回一个 BigDecimal 其值为 (this / divisor) ,其首选比例为 (this.scale() - divisor.scale()) ;如果无法表示确切的商(因为它有一个不终止的十进制扩展),则会抛出 ArithmeticException

参数:

divisor - 此 BigDecimal 要除以的值。

退货:

 this / divisor

投掷:

ArithmeticException - 如果精确商没有终止小数展开

自从:

1.5

如果您在划分时指定比例,例如 dividendo.divide(BigDecimal.valueOf(1000), 0, RoundingMode.HALF_UP) 您将得到相同的结果。

原文由 dcernahoschi 发布,翻译遵循 CC BY-SA 3.0 许可协议

表达式 new BigDecimal("176100000")new BigDecimal("1761e+5") 不相等BigDecimal 跟踪值和精度。

BigDecimal("176100000") BigDecimal("1761e+5") 9 位精度,在内部表示为 BigInteger("1761") BigInteger("176100000") ,乘以 1。 --- ,乘以 100000。

当您将 a BigDecimal 除以一个值时,结果遵循精度数字,导致看似相等的值产生不同的输出。

原文由 Joshua 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题