将非常接近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中也不会出错,因为一位同事报告说他看到它出错了一次就是什么部分促使我提出这个问题。
答案 0 :(得分: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);
该代码段不会产生任何输出。
(Math.ulp
返回给定double和double值之间的距离,接下来大小更大。断言因此确保greatestLessThanOne
确实是小于1.0的最大值。)
换句话说,你的行
Object element = elementArray[(int)(Math.random() * elementArray.length)];
永远不会产生ArrayIndexOutOfBoundsException。
此外,根据马克·迪金森(Mark Dickinsons)对here的评论,这也适用于乘以双倍。
使用围绕最近模式的IEEE 754浮点运算,您可以显示任何
x * y <
的{{1}} y和任何非微小正x < 1.0
。 (如果y
是次正规或最小正正常数,则可能失败。)
答案 1 :(得分:-2)
围绕它,可能是这样的:
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP);