2011-11-08 802 views
16

我刚刚发现难以将重置C(++)的PRNG到srand之前的状态(如reference )。 然而,种子0似乎也是这样做的,或者在调用srand之前的状态似乎使用种子0. 这两个调用之间的区别是什么或者他们做同样的事情的原因是什么?srand(1)和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 
+1

非常有趣的问题。就我所知,srand没有任何“魔术”价值,但rand()只是初始化为1的种子,并且因此从该种子开始,除非被告知不同的东西。这意味着如果你调用srand(1),你会“重置到原始状态”。然而,你发布的输出表明,它真的“神奇地重置”到你以前设置的种子0,而不是1(这就是说,我的实现没有_not_做)。 – Damon

回答

11

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

if (seed == 1) seed = 0; 

强制执行符合标准的行为。

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

+9

实际上,代码更像'if(seed == 0)seed = 1;',因为'rand()'的GNU实现使用的算法不适用于零的种子。 –

7

既不与c也不是C++标准多讲的rand()srand()实施的细节。细节几乎完全取决于实现者。 C标准要求:

如果然后用相同的种子值调用srand,则应重复伪随机数的序列。如果已作出任何函数srand调用之前兰特被调用时,相同的序列应按srand时首先用1

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

0

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

对于0和1两种播种而言,相同的结果最可能取决于实现,不应将其计入所有平台上。

0

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

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

1

如果种子被设置为1,发电机被重新初始化到它的初始值,并产生相同的值,以兰特或函数srand任何呼叫之前。srand参考

15

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标准库的实现。

-3

指定原因1是因为如果种子设置为零,某些随机数生成器将卡住零。例如移位寄存器和乘法同余类型,即r(n+1) = (A * r(n))mod M。许多C实现使用线性同余r(n+1) = (A * r(n) + B) mod M,B <> 0,它们不会卡住。

+0

这与问题有什么关系? – melpomene