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

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

(int)(Math.random() * 8)

是8还是7?

举一个实际的例子,这个经常使用的结构能否给出超出范围的索引错误:
someArray[(int)(Math.random() * someArray.length)];

我对Java和ActionScript 3的答案特别感兴趣,但我想它们都对浮点算术使用相同的规则,并且对于任何平台的答案都将很有用。

更新:尽管我已经接受了一个答案,但我还是很高兴能确认在ActionScript 3中也不会出错,因为一位同事报告说他一次看错了,这在一定程度上促使了我提出这个问题。

最佳答案

如果将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);

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

( Math.ulp 返回给定的double和下一个更大的double值之间的距离。因此,该断言确保greatestLessThanOne实际上是小于1.0的最大值。)

换句话说,你的线
Object element = elementArray[(int)(Math.random() * elementArray.length)];

永远不会引发ArrayIndexOutOfBoundsException。

此外,根据Mark Dickinsons对here的评论,当乘以double时,也是如此。

10-07 19:03