如何不止一次地调用srand会影响随机性的质量?

6 c++ random srand

这条评论指出:

srand(time(0));我会把这一行作为main()中的第一行,而不是多次调用它(这实际上会导致更少的随机数).

......我已经加粗了我遇到问题的界限......重复一个常见的建议,srand在一个程序中调用一次.像srand()这样的问题- 为什么只调用一次?重新迭代,因为time(0)以秒为单位返回当前时间,srand在同一秒内多次调用将产生相同的种子.常见的解决方法是使用毫秒或纳秒.

但是,我不明白为什么这意味着srand应该或只能调用一次,或者它如何导致更少的随机数.

cppreference:

一般来说,伪随机数生成器只应在对rand()的任何调用和程序的开始之前播种一次. 每次您希望生成一批新的伪随机数时,不应重复播种或重新播种.

phoxissrand()的回答- 为什么只召唤一次?:

使用种子值初始化初始状态将生成足够的随机数,因为您没有使用srand设置内部状态, 因此使得数字更可能是随机的.

也许他们只是使用不精确的语言,没有一个解释似乎解释为什么srand多次调用是坏的(除了产生相同的随机数序列)或它如何影响数字的"随机性".有人可以为我清楚这一点吗?

Gal*_*lik 5

std::time(0)函数以秒为单位返回时间.

问题是计算机速度如此之快,以至于在每次请求随机数时调用std::time(0)之间的函数都不会发生变化,std::srand()如果std::srand()每次请求一个随机数时std::srand()都会保持被重置以产生相同的数字序列,直到std::time()函数返回不同的时间(一秒钟)后来).

一秒钟内,您最终可以生成相同数量的数百万次!这不是很随机.


vso*_*tco 2

伪随机发生器是一种产生看起来几乎随机的数字的引擎。然而,它们是完全确定性的。换句话说,给定一个种子x0,它们是通过在 上重复应用某个单射函数(x0称为 )而产生的f(x0),因此这f^m(x0)f^{m-1}(x0)或完全不同f^{m+1}(x0),其中符号f^m表示函数组合m次数。换句话说,f(x)有巨大的跳跃,几乎与之前的跳跃无关。

如果您sradnd(time)在一秒钟内使用多次,您可能会得到相同的种子,因为时钟并不像您想象的那么快。所以生成的随机数序列将是相同的。这可能是一个(巨大的)问题,特别是在密码学应用中(无论如何,在后一种情况下,人们购买基于实时物理过程的良好数字生成器,例如大气数据中的温差等,或者最近,基于测量量子位,例如偏振光子的叠加,只要量子力学是正确的,后者就是真正随机的。)

还存在其他严重问题rand。其中之一是分布有偏差。请参阅http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx进行一些讨论,尽管我记得我在SO上看到过类似的东西,但现在找不到它。

如果您打算在加密应用程序中使用它,请不要这样做。使用<random>像梅森扭曲器这样的严肃随机引擎,std::mt19937并与std::random_device

如果您使用 为随机数生成器播种两次srand,并获得不同的种子,那么您将获得两个完全不同的序列。这可能会让您满意。然而,由于我上面提到的问题,每个序列本身都不会是一个好的随机分布。另一方面,如果您为 rng 播种太多次,您将得到相同的种子,这很糟糕,因为您将一遍又一遍地生成相同的数字。

PS:在评论中看到伪数依赖于种子,这很糟糕。这是伪数的定义,这并不是一件坏事,因为它允许您使用相同的序列重复数值实验。这个想法是,每个不同的种子应该产生一个(几乎)随机数序列,与之前的序列不同(从技术上讲,你不应该能够将它们与完美的随机序列区分开来)。