C/C++的rand()如何快速生成随机数?

3
我的理解是,伪随机数生成器基本上只是取一个数字(种子),对其进行一系列的异或和位移运算,然后输出一个非常长的数字,可以从中获取余数以得到您的“随机”数字。
通常情况下,在C/C++中使用time(NULL)作为rand()的种子。但是,time(NULL)仅每秒递增一次,而不是每毫秒。那么,如果种子仍为相同的time(NULL)值,如何在不到一秒钟的时间内循环一千次rand()并获得不同的输出数字?

9
在循环内调用rand()之前,调用srand(time(NULL));,你会发现输出结果在一秒钟内不会改变。这就是为什么通常只应该在程序开头初始化一次随机数生成器的原因。此外,C++11在<random>头文件中添加了许多更好的随机数生成器。如果你的编译器支持,应该使用它们。 - Praetorian
2
如果你对伪随机数生成器感兴趣,可以看看Donald Knuth的不朽之作《计算机程序设计艺术》。这本书详细介绍了该主题。 - Zaphod Beeblebrox
3个回答

11

rand()函数在后续调用时会将上一个随机数作为新种子来生成下一个随机数。因此,当您使用不同的种子值开始时,将生成一个独特的随机值序列。


啊,这很有道理。 - Coffee Maker
4
虽然这样说最容易理解,但我不认为它在技术上一定(或有效地)准确。随机数生成器(RNG)有状态,每次调用“rand”函数时,它会切换到“下一个”状态,并从当前状态生成伪随机数。 - Mooing Duck
使用先前的随机值作为新种子。至少在种子意味着调用srand()的情况下,这并不成立。(http://coliru.stacked-crooked.com/a/c537c22b36b412b0) - Baum mit Augen
1
@MooingDuck 是的,从技术上讲,只有初始值被称为“种子”。然而,将生成的随机值视为后续调用的新种子可以简化解释,因为在计算上,随机值与第一次调用时使用的种子完全相同。(至少对于线性同余发生器而言。) - Bill the Lizard
@BaummitAugen 我不确定。我看不出你的代码有什么问题。我期望打印出来的值是相同的,但我不知道 rand() 的实现细节。也许值得发一个单独的问题,看看是否有人能解释你的代码的输出。 - Bill the Lizard
显示剩余2条评论

2
一个伪随机数生成器会输出一系列看起来随机的数字,但实际上是在某个范围内的确定性数字序列。 time(NULL) 是所谓的 RNG 种子,它告诉生成器从哪里开始生成数字序列。你应该每个程序只使用一次。
顺便提一下,rand() 不是现代 C++。请参考这里了解原因和替代方案。

0

True,这也是使用rand()被强烈不推荐的原因之一(https://www.securecoding.cert.org/confluence/display/seccode/MSC30-C.+Do+not+use+the+rand()+function+for+generating+pseudorandom+numbers)。 - pjs

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