为什么rand()在fork之后不是那么随机?

时间:2011-12-24 06:34:22

标签: c random fork

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    int i =10;
    /* initialize random seed:  */
    srand(time(NULL));
    while(i--){
        if(fork()==0){
            /* initialize random seed here does not make a difference:
            srand(time(NULL));
             */
            printf("%d : %d\n",i,rand());
            return;
        }
    }
    return (EXIT_SUCCESS);
}

打印相同(每次运行时不同)数量10次 - 预计? 我有一个更复杂的代码片段,每个分叉的进程依次运行 - 没有区别

7 个答案:

答案 0 :(得分:18)

输出必须相同。如果两个进程每个都使用相同的种子播种随机数,并且每次调用rand一次,则必须获得相同的结果。这就是拥有种子的重点。您的所有流程都使用相同的种子调用srand(因为您只调用srand一次)并且他们都会调用rand一次,因此他们必须获得相同的内容结果

取消注释srand不会产生任何影响,因为除非秒数已经改变,否则它们仍将提供相同的种子。你可以这样做:

srand(time(NULL) ^ (getpid()<<16));

答案 1 :(得分:5)

rand()函数是伪随机数字生成器。这意味着生成的数字的序列是确定性的,仅取决于提供的种子。

因为您要将同一个进程分叉10次,所以随机数生成器的状态对于每个子进程都是相同的。下次拨打rand()时,您将获得相同的值。

通过在子进程中调用srand(time(NULL)),您可能帮助,但time()的粒度只有1秒,所以您的所有孩子可能都在同一秒内开始。使用相同值进行播种会生成相同的伪随机序列。

您可以尝试使用取决于子编号的值播种:

srand(time(NULL) - i*2);

(如果i*2在fork循环期间前进1秒,我使用time()。)

答案 2 :(得分:5)

如果您的代码运行得足够快,srand()可能会为每个分叉播种完全相同的时间。 time()只会每秒更改一次。

答案 3 :(得分:2)

甚至在循环中添加srand(time(NULL));(你已注释的if块内的行)没有区别的原因是因为现代计算机可以非常快地执行整个块,并且time以秒计。从手册页:

  

time()返回自Epoch ...以来的秒数...

如果您在sleep(1);循环中的if语句后添加while并取消注释srand来电,则结果会有所不同,因为time现在会返回一个不同的值,因为已经过了一秒钟。

然而,使用不同的种子值而不是等待更合适。像i这样的东西是个好主意,因为它对于循环的每次迭代都是唯一的。

答案 4 :(得分:0)

之所以这样,是因为所有程序都以相同的值播种(在while循环之外)。一旦你分叉了新程序,你就应该再次播种,否则两者都会生成相同的序列。

答案 5 :(得分:0)

进行子进程时,您不会重新播种。随机数生成器的状态完全相同。

即使您再次在您的孩子中播种,您也会以+/- 1秒的粒度播种。当你分叉时,一切都发生在不到一秒钟。

尝试用不同且更随机的东西播种。

答案 6 :(得分:0)

这解决了问题:

srand48((long int)time(NULL));
i= (lrand48()/rand()+1) % 123

我没有使用fork进行测试,但在调用100次之内它可以工作。

带有pid编号的种子。它有点但很难解决问题。

这是在某些页面中:&#34;这是srand(time(0)+ getpid());但我不得不在案例0中称之为,即子过程&#34;。