在随机数生成中,相邻的种子是否会产生类似的随机数?

13

我在模拟中使用连续的种子(1、2、3、4...)来生成随机数。那么这些接近的种子会使生成的伪随机数也相似吗?

我认为这并不会改变任何事情,但是我在使用Python。

编辑:我进行了一些测试,数字看起来并不相似。但我担心只是通过观察数字无法发现相似性。是否存在随机数生成的理论特征,可以保证不同的种子给出完全独立的伪随机数?


2
如果您不信任 RNG(我承认这有点破解),您可以通过 hashlib 中的 SHA1 算法传递种子;该算法旨在将类似的值映射到完全不同的值。 - Fred Foo
我注意到了这种影响,但我认为它是在Microsoft C++中出现的,而不是Python。我相信random模块使用更好的算法。 - Mark Ransom
这是我最近发现的一篇有趣的帖子 :-)。 - Homero Esmeraldo
6个回答

4

根据定义,种子和生成的随机数之间肯定存在相关性。问题在于随机化算法是否足够产生看起来不相关的结果,您应该学习评估随机性的方法来回答这个问题。

您的担忧是正确的。下面是使用0到9的种子值从微软的C++ rand 函数获得的结果:

   38  7719 21238  2437  8855 11797  8365 32285 10450 30612
   41 18467  6334 26500 19169 15724 11478 29358 26962 24464
   45 29216 24198 17795 29484 19650 14590 26431 10705 18316
   48  7196  9294  9091  7031 23577 17702 23503 27217 12168
   51 17945 27159   386 17345 27504 20815 20576 10960  6020
   54 28693 12255 24449 27660 31430 23927 17649 27472 32640
   58  6673 30119 15745  5206  2589 27040 14722 11216 26492
   61 17422 15215  7040 15521  6516 30152 11794 27727 20344
   64 28170   311 31103 25835 10443   497  8867 11471 14195
   68  6151 18175 22398  3382 14369  3609  5940 27982  8047

1
“rand” 在某些平台上是出了名的不可靠。Python 的 “random” 模块使用 Mersenne Twister 算法,虽然不足以用于加密,但比大多数 “rand” 实现要好得多。 - Fred Foo

1
我发现当使用连续的种子进行多次模拟时,从Mersenne Twister生成的随机数存在可测量但很小的相关性——这些结果被平均以产生最终结果。在Linux上使用Python时,如果我使用由系统随机函数(非伪随机数)生成的种子(通过random.SystemRandom()),则这些相关性会消失。我将SystemRandom数字存储在文件中,并在需要模拟种子时读取它们。 生成种子的方法为:
import random
myrandom = random.SystemRandom
x = myrandom.random       # yields a number in [0,1)
dump x out to file...

然后当需要种子时

import random
read x from file...
newseed = int(x*(2**31))  # produce a 32 bit integer
random.seed(newseed)
nextran = random.random()
nextran = random.random()...

你能描述一下你是如何衡量相似度的吗? - Homero Esmeraldo
我无法进入我的特定应用程序,但结果与类似情况几乎相反——附近的随机数(相隔几个调用)略微呈负相关,如果其中一个小于某个小数字(~0.01),那么接下来的几个数字也不太可能小于该小数字。我没有进行广泛的测试,可能有些草率,但在多个具有连续种子的大量模拟实例中存在一致的趋势。 - BugFinder

1

如果您担心顺序种子,那么请不要使用顺序种子。建立一个主RNG,使用已知的种子,并从该主RNG中连续获取输出以根据需要为各个子RNG提供种子。

由于您知道主RNG的初始种子,因此如果需要,可以再次完全按照之前的方式运行整个模拟。

masterSeed <- 42
masterRNG <- new Random(masterSeed)

childRNGs[] <- array of child RNGs

foreach childRNG in childRNGs
   childRNG.setSeed(masterRNG.next())
endforeach

2
我不确定这是否是一个好主意,因为你有可能会重复种子。例如,如果你正在生成16位数字并运行数千个进程,那么这种情况很可能发生。 - Will
2
问题询问的是连续种子,而不是重复种子。如果重复种子是一个问题,那么使用一个128位块密码,并加密数字0、1、2、3,... 2^128-1。作为密码,这些数字保证在很长一段时间内不会重复,直到计数器翻转。不同的密钥将给出数字的不同排列。要复制排列,请使用相同的密钥。 - rossum
1
-1 是因为存在重复种子的风险。最好在答案中包含没有重复风险的方法和代码,而不仅仅是注释。 - Homero Esmeraldo

0
首先:定义相似性。接下来:编写相似性测试。然后:检查相似性。
只有一个模糊的相似性描述,很难进行检查。

0
你在做什么样的模拟?
如果是为了模拟目的,你的论点是正确的(取决于模拟类型),但如果你在非模拟环境下实施它,那么如果生成的随机数需要考虑环境的安全问题,它很容易被黑客攻击。
如果你正在模拟一台机器的结果,无论它对社会是否有害,你的结果都不会被接受。它需要尽可能地随机化,我永远不会相信你的推理。

0

引用随机模块文档:

关于底层Mersenne Twister核心生成器的一般说明:

  • 周期为2 ** 19937-1。
  • 它是现存最经过广泛测试的生成器之一。

我更担心我的代码会出问题,而不是我的RNG不够随机。总的来说,你对随机性的直觉感觉可能是错误的 - 即使没有实际存在的模式,人类大脑也很擅长找到模式。

只要你知道由于缺乏随机种子,你的结果不会“安全”,那么你就应该没问题了。


抱歉,您的意思是什么:“由于缺乏随机种子,您的结果不会是‘安全的’”?您所说的“安全”是什么意思?您是否确实在说由于我的顺序播种而不安全?这似乎与您之前关于随机模块值得信赖的说法相矛盾... - Homero Esmeraldo
@Homero:我的意思是,如果您正在将这种随机性应用于任何安全目的,那么您就容易受到了解您播种方法的任何人的攻击。 另一方面,如果您正在运行某种模拟并希望获得可重复的结果,那么您应该获得足够的随机性。 - Sean McSomething
1
-1 是因为问题是关于一系列相关种子如何影响生成的随机数的质量,而不是基于单个种子时随机数的质量。例如,在多线程程序开始时创建许多不同的生成器(可能每个线程一个)时,这个问题是相关的。您希望避免生成器之间的相关结果。我认为 @rossum 的答案是解决这个问题的好方法。 - Tyler Streeter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接