srand(1)和srand(0)之间有什么区别

我刚刚发现srand(1)在调用srand (如参考文献中定义)之前将C(++)的PRNG重置为状态的困难方式。 然而,种子0似乎做同样的事情,或者在调用srand之前的状态似乎使用种子0.这两个调用之间有什么区别或者他们做同样事情的原因是什么?

例如这段代码( 在Ideone上执行 )

 #include  #include  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 

这可能是一个实现细节。 标准要求随机种子1是特殊的,并且您的特定随机生成器算法的内部寄存器可能是零初始化的,因此导致种子(0)和种子(1)的相同随机序列。 我甚至打赌你的srand()实现的第一行看起来像:

 if ( seed == 1 ) seed = 0; 

强制符合标准的行为。

通常,rand()和srand()的随机数生成器不需要为不同的种子提供不同的序列,但是对于相同的种子使用相同的序列。 所以, 不要依赖不同的种子产生不同的随机序列 ,你应该没事。 如果没有,欢迎特定实施的乐趣。

glibc是如何做到的:

在glibc / stdlib / random_r.c的第181行附近 ,函数__srandom_r

  /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ if (seed == 0) seed = 1; 

但这就是glibc如何做到的。 这取决于C标准库的实现。

C和C ++标准都没有说明rand()srand()实现的细节。 细节几乎完全取决于实现者。 C标准要求:

如果随后使用相同的种子值调用srand,则应重复伪随机数序列。 如果在对srand进行任何调用之前调用rand,则应该生成与第一次调用srand且种子值为1时相同的序列。

但它不包含任何要求不同种子必须产生不同序列的要求。 显然,在你的系统上,零和一的种子具有相同的效果。 我猜这是为了向某些软件提供向后兼容性,这些软件期望srand(0)将PRNG重置为其初始状态。

如果seed设置为1,则将生成器重新初始化为其初始值,并生成与调用rand或srand之前相同的值。 取自srand参考

在阅读手册页时,它们都声明“如果没有提供种子值,则rand()函数会自动播种,值为1”。 这可能是您链接到状态的参考页面,其中播种1会重置状态。

对0和1两者进行播种的结果相同,很可能取决于实现,并且不应计入所有平台上。

srand()函数使用该参数作为后续调用rand()返回的新伪随机数序列的种子。 如果随后使用相同的种子值调用srand(),则应重复伪随机数序列。 如果在对srand()进行任何调用之前调用rand(),则应生成与首次调用种子值为1的srand()时相同的序列。

也许有用: http : //pubs.opengroup.org/onlinepubs/009695399/functions/rand.html

指定原因1是因为如果将种子设置为零,则某些随机数生成器将停留在零。 例如移位寄存器和乘法同余类型,即r(n+1) = (A * r(n))mod M

许多C实现使用线性同余r(n+1) = (A * r(n) + B) mod M ,B <> 0,它们不会被卡住。