乘以0.99999999999是否可以舍入到1.0?
当将一个非常接近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中不会出错,因为一个同事报告他看到它出错一次是什么部分促使我问这个问题。
如果用someInt
(> 0)乘以1.0以下的someInt
,结果永远不会是someInt
。
这可以穷举testing这样的整数:
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
Math.ulp
确实是小于1.0的最大值)。
换句话说,你的路线
Object element = elementArray[(int)(Math.random() * elementArray.length)];
将永远不会引发ArrayIndexOutOfBoundsException。
此外,根据马克·迪金森在这里的评论,这也成立了倍增倍数。
在IEEE 754浮点运算处于最接近的模式下,可以显示任何
x < 1.0
和任何非微小正y
x * y <
y
。 (如果y
是低于正常值或是正常的最小正数,则可能失败。)
围绕它,可能是这样的:
BigDecimal bd = new BigDecimal(Double.toString(d)); bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP);