当乘以时,可以将0.99999999999四舍五入为1.0吗?

Bar*_*lom 35 java math floating-point actionscript-3

当将非常接近1的浮点数乘以int> 0时,它是否可以解释为1.

也就是说,如果Math.random()返回其最高可能结果(比1.0低1步),将会

(int)(Math.random() * 8)
Run Code Online (Sandbox Code Playgroud)

是8还是7?

对于一个实际的例子,这个经常使用的构造是否可以提供索引超出范围的错误:

someArray[(int)(Math.random() * someArray.length)];
Run Code Online (Sandbox Code Playgroud)

我对Java和ActionScript 3的答案特别感兴趣,但我想它们都使用相同的浮点运算规则,任何平台的答案都会很有用.

更新:虽然我已经接受了答案,但我仍然感谢确认这在ActionScript 3中也不会出错,因为一位同事报告说他看到它出错了,这部分促使我提出这个问题.

aio*_*obe 45

如果将1.0以下的最大值乘以someInt(> 0),结果将永远不会someInt.

这可以对这样的整数进行详尽的测试:

Double greatestLessThanOne = Double.longBitsToDouble(4607182418800017407L);

// Assert that greatestLessThanOne is indeed the largest double less than 1.
//assert 1.0 == greatestLessThanOne + Math.ulp(greatestLessThanOne);

for (int i = 1; i >= 0; i++)
    if ((int) (greatestLessThanOne * i) == i)
        System.out.println("Exception found: " + i);
Run Code Online (Sandbox Code Playgroud)

该代码段不产生任何输出.

(Math.ulp返回给定double和double值之间的距离,接下来是幅度更大.断言因此确保它greatestLessThanOne确实是小于1.0的最大值.)

换句话说,你的路线

Object element = elementArray[(int)(Math.random() * elementArray.length)];
Run Code Online (Sandbox Code Playgroud)

永远不会产生ArrayIndexOutOfBoundsException.


此外,根据Mark Dickinsons在这里的评论,这也适用于乘以双倍.

使用围绕最接近模式的IEEE 754浮点运算,您可以显示x * y <任意x < 1.0和任何非微小正数的y y.(如果y是次正规或最小的正正常数,它可能会失败.)

  • 好答案.而[Java](http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html)使用舍入到最近:"Java编程语言要求浮点算法表现得好像每个浮点运算符将其浮点结果四舍五入到结果精度.不精确的结果必须四舍五入到最接近无限精确结果的可表示值;如果两个最接近的可表示值相等接近,则其最低有效位为零选择.这是IEEE 754标准的默认舍入模式,称为**舍入到最接近的**." (2认同)