Java Random,种子变化很小,只会导致输出变化不大

时间:2011-05-28 19:49:01

标签: java random seed

在使用Java创建地图生成器时,我发现它们的随机数生成器存在一个相当令人不安的问题,要指定当两个RNG具有非常相似的种子(小整数不同)时,它们的第一个输出值将变得非常相似!

示例代码:

Random r = new Random();
long n = 100000; //Choose any number
r.setSeed(n);  
System.out.println(r.nextInt());
r.setSeed(n+1);
System.out.println(r.nextInt());

这几乎打破了我对原始Java RNG的信心,因为我使用坐标为地图生成器播种。 有人可以建议重新定义Random.next(int bits)方法,还是针对此问题进行其他修复?

感谢您的帮助!

4 个答案:

答案 0 :(得分:8)

您是否比较了从100000和100001得到的前20个值的序列?

这是种子100000和100001的第20个下一个种子。在第三列中有不同位的数量(2之间的xor的bitcount)

这最后一列应保持在16左右

-1986972922 -1987357671 13
-1760380366 -604895790  16
-1057894078 -329706441  15
-363772240  -1218064509 15
1545317691  -300240831  14
271304166   -900428132  21
1208561582  273461468   16
-1257783052 1069490639  16
-1549884799 40157720    15
-1514737808 -1818800021 17
-1030569735 1859508545  15
1310070992  880402584   18
-1513092400 971613287   19
-1993219517 354161779   16
-10847170   -204018237  15
-965377044  1488135032  14
802471291   1094582308  22
-539776032  -1021376555 15
2088199751  2070302462  12
-1271582124 64627614    19

在3-5次迭代后不太相似

除了标准的Random之外,还实现了一个线性同余RNG,它已知不是现有的最佳伪随机实现,但对存储器的效率最高(2^48周期只有一个64位字)

感兴趣的乘数为0x5deece66dL,c为0xbL

答案 1 :(得分:2)

你的两粒种子(PRNG州)只有最低位才有所不同。考虑到PRNG通常只做一些xor-ing和转移,这不应该太令人惊讶。

无论如何,你不应该像这样使用Random。在每个nextInt方法上,PRNG的状态将被更新(状态/种子将改变48个可用位的约50%)。这就是你应该关心的一切。

答案 2 :(得分:1)

据我所知,您需要一系列依赖于某些计算种子的随机数,这样您就可以在给定相同种子时随时重新生成序列。是吗?

由类似种子生成的随机数序列开始相似,但很快就会发散。如果只跳过前k个值,您可能会得到更符合您需求的结果。在这里,k是你必须根据你对序列的不同程度和计算速度的需要来确定的数字。

答案 3 :(得分:0)

引入了{p> java.security.SecureRandom来处理java.util.Random中的问题,例如问题中描述的问题。 SecureRandom没有表现出相同的可预测性(至少,它并不是那么明显)。您可以在代码中使用SecureRandom而不是Random来解决问题,因为前者是后者的子类。

有人可能想知道为什么Sun在发现此问题后不仅修复了Random。原因是向后兼容性 - Random的行为无法更改,因为它会破坏依赖于任何给定种子生成的特定伪随机序列的现有代码。