我正在实施一个SkipList。在算法的某一点上,我们要扔一枚硬币,并且只要它不断出现就一遍又一遍地做一些事情,并在我们看到尾巴时立即停止。我通过使用:
让奇数代表“头”while (R.nextInt() % 2 == 1)
但是这只产生了大约25%的时间(在50,000次呼叫中)。将其更改为
while (R.nextBoolean())
正如预期的那样,产生头部的一半时间。 R被实例化为随机,用System.currentTimeMillis()播种。看来,Random生成的比特流毕竟不是那么均匀分布的。有没有人见过这种行为?
我也尝试过:
while (Math.random() >= 0.5)
并获得了我期待的50/50(给予或接受)行为。
它似乎也适用于:
while (R.nextInt(2) == 1)
在一半的时间内,LSB 0似乎没有生成32位整数。似乎在比特级别,我们也应该能够期待随机性。也许这是他们正在使用的线性一致性;也许我错过了什么,但这似乎是一个问题。我意识到有更好的PRNG可用,我已经有一些完全可行的解决方案;我只是想报告我观察到的内容。
答案 0 :(得分:6)
nextInt()
返回下一个伪随机数,从该随机数生成器的序列中均匀分布的int值。
整数类型用Java签名,模式2
操作的可能结果是:-1
(负奇数),0
(偶数),1
(正数)奇)。
nextInt() % 2
仅对正奇数整数等于1
,这就是为什么你只得到25%。您需要对条件进行一些小改动:
while (R.nextInt() % 2 != 0)
答案 1 :(得分:2)
如果(n*2+1) % 2
为负数,则n
为-1。 (这很烦人,因为它没有多少数学意义,但它就是它。它与/
运算符的工作方式一致,因此(a/b)*b+(a%b)=a
对所有a
和b
,除非发生整数溢出。)
由于Random.nextInt()
返回带符号的随机数,因此模数将为50%的时间,-1 25%的时间和1 25%的时间。
当然,您可以切换到r.nextInt() % 2 != 0
或r.nextInt() == 0
,但最易读的解决方案确实只是使用r.nextBoolean()
。