【问题标题】:Java - How to avoid loss of precision during divide and cast to int?Java - 如何避免在除法和转换为int期间丢失精度?
【发布时间】:2024-01-10 04:33:01
【问题描述】:

我有一种情况,我需要找出一个 int 进入小数的次数,但在某些情况下,我会失去精度。方法如下:

public int test(double decimalAmount, int divisor) {
  return (int) (decimalAmount/ (1d / divisor));
}

问题在于,如果我将 1.2 作为小数并传入 5 作为除数,我得到的是 5 而不是 6。我怎样才能重新信任它,以便我知道 5 作为 int 有多少次进入小数?

【问题讨论】:

  • 我认为您需要给出一个更通用的问题版本-您使用的术语仅对整数有意义,即 5 除以 1.2 = 0/如果您确实改进了定义,我怀疑您会得到答案,因为我怀疑问题是由于四舍五入
  • 这与舍入无关,与公式有关。小数除以 int 很简单 (int)(decimalAmount/divisor)。我认为这就是大卫正在寻找的。就目前而言,代码实际上是在做小数和除数的乘法。

标签: java casting int precision


【解决方案1】:
public int test(double decimalAmount, int divisor) {
  return (int) (divisor * decimalAmount);
}

显然,这只是相乘然后截断。为什么你认为你需要这种方法?

【讨论】:

    【解决方案2】:

    计算结果可能类似于 5.999999999994,因为浮点结果不一定是整数。当您转换为 int 时,您会截断,结果为 5。对于另一组类似的参数,您可能会看到 6.0000000000002 的结果,它会给您 6。

    但它对浮点表示如此敏感的事实让人质疑为什么你认为你想要这个——也许有更好的方法来做你想做的事。比如上面的答案是正确的,这样就简化了,然后就更不清楚重点是什么了。

    要真正做我认为你想做的事,你不需要使用doubles 或floats。你需要java.util.BigDecimal——看看它是如何工作的。你可以用它来“精确地”乘以 5 和 1.2 得到 6。

    【讨论】:

    【解决方案3】:

    浮点运算不正确,它们是近似值。通过此操作,您可以获得例如 5.9 作为结果。将其转换为 int 结果为 5(而不是 6)。尝试舍入而不是截断:

    public int test(double decimalAmount, int divisor) {
      return Math.round(divisor * decimalAmount);
    }
    

    【讨论】: