出于好奇,Math.random()会为零吗?
例如,如果我有:
while (true){
if (Math.random() == 0)
return 1;
}
我真的能得到1的回报吗?还需要考虑舍入误差,因为Math.random()返回一个双精度值。
我之所以这样问,是因为我的CS教授指出,random()从0到1(包括0和1),我一直认为它是独占的。
发布于 2010-06-18 04:55:43
根据the documentation的说法,“返回一个带正号的双精度值,大于或等于0.0且小于1.0。”这意味着它可以是零。
作为Hank wrote,它在上限上是唯一的(永远不会是1),所以这可能就是你混淆的原因:-)。
发布于 2010-12-07 06:16:17
是的,真的可以。Math.random()
使用种子-generator创建全局java.util.Random
-generator,并为其调用nextDouble()
。如果它的种子达到状态107048004364969L
(它会达到状态,因为java.util.Random
有完整的周期),那么生成的下一个double
将是0.0
。不过,如果运气不好,您可能会在循环中得到错误的奇偶校验,因为Random.nextDouble()
会将状态向前推进两次。不幸的是,在循环结束之前,您可能需要生成2^47个随机数,因为我没有找到任何其他提供0.0
的种子。
种子就像通过seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
一样前进,并且使用两个连续种子值的26和27个高位来生成双精度。在本例中,下一个种子值将是0L
和11L
。
如果您设法用System.currentTimeMillis()==107038380838084L
创建了全局生成器,您的代码将立即返回。您可以使用以下命令来模拟此过程:
java.util.Random k = new java.util.Random(107038380838084L);
System.out.println(k.nextDouble()==0);
发布于 2010-06-18 07:22:31
它完全有可能永远不会恰好返回零。Java自带的PRNG是一个48位的LCG,其中只使用了32位。要使double
尾数的所有53位都为0,基本上需要至少一次调用next()
,其中高32位为0,另一次调用高32位为0。(如果我没记错的话,我会说这永远不会发生在生成器的工作方式上,但是现在已经很晚了,我累了,我不会下太大的赌注。)
由于方法文档明确说明了如何获得随机数,因此Java运行时的其他实现也没有多少余地来产生不同的结果。合同可能会说你得到的数字来自[0,1]。但在实践中,有相当多的值您永远不会命中(因为您需要来自生成器的两个连续的值,它们强制地在连续的值之间产生线性依赖--只有48位的状态。您不能从中生成所有不同的53位组合-至少不能生成它的实现方式。)
当然,由于Math.random()
会自动为静态Random
实例设定种子,因此我们可能还需要考虑此处的种子,它可能需要非常具体才能使测试用例生效。这可能意味着那个确切的时间点可能还需要几十年或几千年的时间。
https://stackoverflow.com/questions/3065554
复制相似问题