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

mrp*_*pyo 5 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
Run Code Online (Sandbox Code Playgroud)

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

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

i == m
Run Code Online (Sandbox Code Playgroud)

Nay*_*uki 5

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

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

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

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

  • +1由于`double`具有53位精度,你将它除以并乘以小于'2 ^ 31`,结果应该小于'1/2 ^ 21 = 2*1/2 ^ 22`(因子) 2是来自两个操作).所以四舍五入将是一个很大的整数. (2认同)

Atr*_*eys 4

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

如果 ulp 超过1/(n),则对乘法进行舍入将无法恢复原始除法 int。通常,较大的 ulp 与较大的双精度值相关。与双精度相关的 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");
  }
Run Code Online (Sandbox Code Playgroud)

输出是:

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

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