Java.Random.nextInt()中令人费解的行为
我正在实现一个SkipList。在算法中的某一点上,我们要掷硬币,反复做一些事情,只要它一直朝着正面,一旦我们看到反面就停止。我让奇数代表“头”,方法是:Java.Random.nextInt()中令人费解的行为,java,Java,我正在实现一个SkipList。在算法中的某一点上,我们要掷硬币,反复做一些事情,只要它一直朝着正面,一旦我们看到反面就停止。我让奇数代表“头”,方法是: while (R.nextInt() % 2 == 1) 但这只在大约25%的时间里(在50000个ish电话中)产生了一个人头。改成 while (R.nextBoolean()) 正如预期的那样,有一半的时间产生头部。R被实例化为一个随机变量,以System.currentTimeMillis()作为种子。看来随机产生的比特流毕竟不是
while (R.nextInt() % 2 == 1)
但这只在大约25%的时间里(在50000个ish电话中)产生了一个人头。改成
while (R.nextBoolean())
正如预期的那样,有一半的时间产生头部。R被实例化为一个随机变量,以System.currentTimeMillis()作为种子。看来随机产生的比特流毕竟不是均匀分布的。还有谁见过这种行为吗
我也尝试过:
while (Math.random() >= 0.5)
得到了我所期待的50/50(给予或接受)的行为
它似乎也适用于:
while (R.nextInt(2) == 1)
它似乎在接近一半的时间里都不会生成LSB为0的32位整数。看起来,在比特级别,我们也应该能够期望随机性。也许他们使用的是线性同余;也许我遗漏了什么,但这似乎是个问题。我意识到有“更好”的PRNG可用,我已经有了一些完全可行的解决方案;我只是想报告我观察到的情况
nextInt()返回此随机数生成器序列中的下一个伪随机、均匀分布的int值 整数类型在Java中是有符号的,执行模运算
2
的可能结果是:-1
(负奇数)、0
(偶数)、1
(正奇数)
nextInt()%2
仅对正奇数整数等于1
,这就是为什么只有25%。您需要在条件上做一些小的改变:
while (R.nextInt() % 2 != 0)
在Java(n*2+1)中,如果n
为负,则2
为-1。(这很烦人,因为它在数学上没有多大意义,但它就是这样。然而,它与/
操作符的工作方式是一致的,所以(a/b)*b+(a%b)=a
对于所有a
和b
而言,除非发生整数溢出。)
由于Random.nextInt()
返回一个带符号的随机数,因此模将为0 50%的时间,-1 25%的时间和1 25%的时间
当然,您可以切换到
r.nextInt()%2!=0
或r.nexttint()==0
但最具可读性的解决方案实际上只是使用r.nextBoolean()
有趣——我认为%总是产生介于0和(模数-1)之间的值(即任何mod 5都必须是0-4,包括在内)。我确实尝试过使用while((R.nextInt()&1)==1)
,而且似乎也像预期的那样工作。@user8887287如果需要,请使用Math.floorMod。