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

Flo*_*ogo 18 c c++ random srand

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

例如这段代码(在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;
}
Run Code Online (Sandbox Code Playgroud)

回报

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
Run Code Online (Sandbox Code Playgroud)

Tha*_*hai 18

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;
Run Code Online (Sandbox Code Playgroud)

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


thi*_*ton 12

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

if ( seed == 1 ) seed = 0;
Run Code Online (Sandbox Code Playgroud)

强制符合标准的行为.

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

  • 实际上,代码更像是`if(seed == 0)seed = 1;`,因为`rand()`的GNU实现所使用的算法不适用于零种子. (11认同)

Ste*_*non 7

无论是Ç,也不是C++标准说太多关于实施的具体细节rand()srand().细节几乎完全取决于实现者.C标准要求:

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

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