繁体   English   中英

在 Java 中如何从 double 转换为 int?

[英]How does conversion from double to int work in Java?

对于以下代码(Java):

double d = (double) m / n; //m and n are integers, n>0
int i = (int) (d * n);

i == m

最后一个表达式总是正确的吗? 如果不是,这总是正确的吗?:

i = (int) Math.round(d * n);

i == m

int i = (int) (d * n); i == m;

对于 m=1,n=49,这是错误的。

i = (int) Math.round(d * n); i == m;

我的直觉告诉我这应该是真的,但可能很难严格证明。

您提出的第二个问题涉及 Java 中的ulp有多大。

如果 ulp 超过1/(n) ,则乘法四舍五入将不会恢复原始除法整数。 通常,较大的 ulp 与较大的双精度值相关联。 与双精度相关的 ulp 在 9E15 左右开始超过 1; 如果您恢复的双打就在那里,那么您可能会发现 round() 没有得到预期答案的问题。 但是,当您使用 int 值时,除法分子的最大值将是Integer.MAX_VALUE

以下程序测试n的所有正 integer 值,以查看在尝试恢复已划分的 int 时哪一个导致舍入误差的最大可能性:

  public static void main(String[] args)
  {
    // start with large number
    int m = Integer.MAX_VALUE;
    double d = 0;

    double largestError = 0;
    int bigErrorCause = -1;
    for (int n = 1; n < Integer.MAX_VALUE; n++)
    {
      d = (double) m / n;
      double possibleError = Math.ulp(d) * n;
      if (possibleError > largestError)
      {
        largestError = possibleError;
        bigErrorCause = n;
      }
    }
    System.out.println("int " + bigErrorCause + " causes at most "
        + largestError + " error");
  }

output 是:

int 1073741823 最多导致 4.768371577590358E-7 错误

使用 Math.round 进行舍入,然后转换为 int 应该恢复原始 int。

从数学上讲,它应该是正确的。 但是,您可能会遇到浮点舍入错误,从而使其错误。 您几乎不应该使用==比较浮点精度数。

你最好使用这样的阈值来比较它们:

Math.abs( d*n - m ) < 0.000001;

注意这两个语句应该是等价的

i = (int) (d * n);
i = (int) Math.round(d * n);

但是,例如,如果d=3/2n=2 ,浮点错误可能会导致i=2.999999999999在截断/舍入后为 2。

第一个绝对不总是正确的。 第二个我会说是的,这是真的,但只是因为我想不出一个反例。

如果 n 非常大,它可能是错误的,我不确定。 我知道这至少在 99% 的情况下都是正确的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM