我刚刚发现srand(1)
在调用srand
之前将{C(+)的PRNG重置为状态的困难方式(如reference中所定义)。
但是,种子0似乎做同样的事情,或者在调用srand
之前的状态似乎使用种子0。
这两个电话有什么不同,或者他们做同样事情的原因是什么?
例如此代码(execute on Ideone)
#include <stdio.h>
#include <stdlib.h>
int main() {
for (int seed = 0; seed < 4; seed++ ) {
printf( "Seed %d:", seed);
srand( seed );
for(int i = 0; i < 5; i++ )
printf( " %10d", rand() );
printf( "\n");
}
return 0;
}
返回
Seed 0: 1804289383 846930886 1681692777 1714636915 1957747793
Seed 1: 1804289383 846930886 1681692777 1714636915 1957747793
Seed 2: 1505335290 1738766719 190686788 260874575 747983061
Seed 3: 1205554746 483147985 844158168 953350440 612121425
答案 0 :(得分:18)
glibc是如何做到的:
around line 181 of glibc/stdlib/random_r.c,内部函数
__srandom_r
/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ if (seed == 0) seed = 1;
但这就是glibc如何做到的。这取决于C标准库的实现。
答案 1 :(得分:12)
这可能是一个实施细节。标准要求随机种子1是特殊的,并且您的特定随机生成器算法的内部寄存器可能是零初始化的,因此导致种子(0)和种子(1)的相同随机序列。我甚至打赌你的srand()实现的第一行看起来像:
if ( seed == 1 ) seed = 0;
强制符合标准的行为。
通常,rand()和srand()的随机数生成器不需要为不同的种子提供不同的序列,但是对于相同的种子使用相同的序列。所以,不依赖于产生不同随机序列的不同种子,你应该没问题。如果没有,欢迎特定于实现的乐趣。
答案 2 :(得分:7)
C和C ++标准都没有对rand()
和srand()
的实施细节作出太多说明。细节几乎完全取决于实现者。 C标准要求:
如果然后使用相同的种子值调用srand,则应重复伪随机数序列。如果在对srand进行任何调用之前调用rand,则应该生成相同的序列,就像第一次使用种子值1调用srand时一样。
但它不包含不同种子必须产生不同序列的任何要求。显然,在你的系统上,零和一的种子具有相同的效果。我猜这是为了向某些软件提供向后兼容性,这些软件希望srand(0)
将PRNG重置为初始状态。
答案 3 :(得分:1)
如果seed设置为1,则将生成器重新初始化为其初始值,并生成与调用rand或srand之前相同的值。取自srand引用 p>
答案 4 :(得分:0)
当阅读手册页时,它们都声明“如果没有提供种子值,则rand()函数会自动播种,值为1”。这可能是您链接到状态的参考页面,其中播种1会重置状态。
对于0和1播种同样的结果很可能取决于实现,并且不应计算在所有平台上发生。
答案 5 :(得分:0)
srand()函数使用该参数作为后续调用rand()返回的新伪随机数序列的种子。如果随后使用相同的种子值调用srand(),则应重复伪随机数序列。如果在对srand()进行任何调用之前调用rand(),则应该生成与第一次使用种子值1调用srand()时相同的序列。
也许有用:http://pubs.opengroup.org/onlinepubs/009695399/functions/rand.html
答案 6 :(得分:-3)
指定原因1是因为如果种子设置为零,某些随机数生成器将卡在零。例如移位寄存器和乘法同余类型,即r(n+1) = (A * r(n))mod M
。
许多C实现使用线性同余r(n+1) = (A * r(n) + B) mod M
,B&lt;&gt; 0不会卡住。