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

时间:2011-08-10 17:45:21

标签: java floating-point double int rounding

对于以下代码(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

4 个答案:

答案 0 :(得分:5)

  

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

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

  

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

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

答案 1 :(得分:4)

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

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

以下程序测试n的所有正整数值,以便在尝试恢复分割的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");
  }

输出结果为:

  

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

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

答案 2 :(得分:1)

数学上应该是真的。但是,您可能会得到浮点舍入错误,这将导致错误。您几乎不应该使用==比较浮点精度数字。

使用这样的阈值比较它们要好得多:

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。

答案 3 :(得分:1)

第一个绝对并非总是如此。第二个我会说是的,这是真的,但仅仅是因为我无法想到一个反例。

如果n非常大,可能是假的,我不确定。我知道至少99%的时间都是如此。

相关问题