如何在C 中实现rand()/ srand()函数

可能重复:
rand()如何工作? 它有一定的倾向吗? 有没有比这更好用的东西?

我知道如何实现它。 但是,我想了解rand在内部是如何表现的,为什么有必要初始化rand函数的’seed’值。

或者说 – rand函数如何使用种子值生成随机数?

确切的实现细节取决于实现者。 但是GNU实现(glibc)实现了rand(): http : //sourceware.org/git/? p = glibc.git; a = blob; f = stdlib / random_r.c; hb = glibc-2.15#l361

评论很好地解释了它。

/* If we are using the trivial TYPE_0 RNG, just do the old linear congruential bit. Otherwise, we do our fancy trinomial stuff, which is the same in all the other cases due to all the global variables that have been set up. The basic operation is to add the number at the rear pointer into the one at the front pointer. Then both pointers are advanced to the next location cyclically in the table. The value returned is the sum generated, reduced to 31 bits by throwing away the "least random" low bit. Note: The code takes advantage of the fact that both the front and rear pointers can't wrap on the same call by not testing the rear pointer if the front one has wrapped. Returns a 31-bit random number. */ 

关于你的问题为什么你总是需要一个种子价值:计算机科学中没有真正随机的数字。 计算机(在计算理论中)是完全确定性的机器。 他们不能以一种偶然的结果执行任何操作。

只有伪随机数生成器生成看起来随机的数字流,但它们仍然是确定性计算的结果。 这就是您需要种子值的原因:每个种子都会产生不同的数字序列。 当您使用相同的种子时,您将获得相同的伪随机数序列。

可以利用RNG在获得相同种子时始终返回相同序列的行为:例如,经典空间模拟Elite能够在一个整数中存储具有数百个行星的巨大宇宙。 它是怎么做到的? 整个宇宙是随机生成的。 重新创建Universe所需的所有数据都是种子值,这总是导致生成完全相同的Universe。

有关更详细的说明,请参阅Wikipedia 。

线性同余生成器(LCG)代表了最古老和最着名的伪随机数生成器算法之一。[1] 它们背后的理论很容易理解,并且很容易实现和快速。

生成器由递归关系定义:

X_ {n + 1} =(a * X_n + c)mod m

大多数rand实现都是LCG ,它使用基本数学来执行混合。 像大多数PRNG一样,它要求随机种子通过使用固定和可预测的数学函数来部分地去除其确定性(这是好的和坏的,取决于它的预期用途)。

如果您对在实践中使用什么算法来实现rand()感兴趣,那么C的rand()使用了哪些常用算法? 可能有趣。 glibc的实现以及解释其他算法的文章的一些链接。

至于为什么必须设置种子的问题,种子是阻止随机数生成器每次产生相同数字序列的原因。 由于没有真正的随机数生成器,如果你调用srand(constant)rand() 5次,你得到的5个“随机”数字将始终是相同的。 但是,如果每次使用rand()使用的值都是不同的(默认值是我认为自Unix时代以来的秒数),那么您将不会遇到此问题。