当将非常接近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时,也是如此。