Java随机,种子的微小变化仅导致输出的微小变化

发布于 2024-11-11 01:19:11 字数 424 浏览 1 评论 0原文

在用 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) 方法,或者对此问题进行其他修复吗?

感谢您的帮助!

While making a map generator in Java I found a rather unnerving problem with their random number generator, to specify, when two RNGs have very similar seeds (differing in small integers) their first output value will become very similar!

Example code:

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());

This pretty much broke my faith in the original Java RNG, since I use coordinates to seed a map generator.
Could someone suggest either a redefinition for the Random.next(int bits) method, or some other fix for this problem?

Thank you for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

木有鱼丸 2024-11-18 01:19:11

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

这些分别是种子 100000 和 100001 的前 20 个 nextInts。在第三列中,不同位的数量(2之间的异或的位数)

最后一列应该保持在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次迭代后不那么相似,

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

对于感兴趣的乘法器来说, 0x5deece66dL 且 c 为 0xbL

did you compare the sequence of the first ~20 values you get from 100000 and 100001?

these are the first 20 nextInts of seeds 100000 and 100001 resp. with in the third column the amount of different bits (bitcount of the xor between the 2)

this last column should remain around 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

not so similar after 3-5 iterations he

besides the standard Random implements a linear congruential RNG which is known not to be the best pseudo-random implementation in existence but the most efficient with memory (only one 64bit word for a period of 2^48)

for the interested the multiplier is 0x5deece66dL and c is 0xbL

尬尬 2024-11-18 01:19:11

您的两个种子(PRNG 状态)仅在最低有效位上有所不同。考虑到 PRNG 通常只是进行一些异或运算和移位,这应该不会太令人惊讶。

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

Your two seeds (PRNG states) differ only by the least significant bit. Considering that PRNGs usually just do some xor-ing and shifting this shouldn't be too surprising.

You shouldn't use Random like this anyway. The state of the PRNG will be updated (state / seed will change by about 50 % of the 48 available bits) upon each nextInt method. That's all you should care about.

2024-11-18 01:19:11

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

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

As I understand, you want a sequence of random numbers that depends on some computed seed, such that you can re-generate the sequence any time when given the same seed. Is that right?

The random number sequence generated by similar seeds starts similar, but soon diverges. You might get results that better fit your need, if you just skip over the first k values. Here, k is a number you have to determine, according to your need of dissimilarity of the sequence and speed of computation.

忆伤 2024-11-18 01:19:11

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

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

java.security.SecureRandom was introduced to deal with problems in java.util.Random such as the one described in the question. SecureRandom does not exhibit the same predictability (at least, it is not as blatantly obvious). You can fix the problem by using SecureRandom in your code instead of Random as the former is a subclass of the latter.

One might wonder why Sun didn't just fix Random after this problem was discovered. The reason is backward compatibility -- the behaviour of Random could not be changed because it would break existing code that depended upon the particular pseudo-random sequence generated by any given seed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文