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

#include  #include  #include  #include  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次 – 预计? 我有一个更复杂的代码片段,每个分叉的进程依次运行 – 没有区别

输出必须相同。 如果两个进程每个都使用相同的种子对随机数进行种子处理,并且每次调用rand一次,则它们必须得到相同的结果。 这就是拥有种子的重点。 所有进程都使用相同的种子调用srand (因为你只调用一次srand )并且它们都调用rand一次,所以它们必须得到相同的结果。

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

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

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

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

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

您可以尝试使用取决于子编号的值进行种子设定:

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

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

如果你的代码运行得足够快,那么srand()可能会为每个fork提供完全相同的时间。 time()每秒只会改变一次。

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

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

如果你加一个sleep(1);while循环中的if语句之后并取消注释srand调用,结果将是不同的,因为time现在将返回不同的值,因为已经过了一秒。

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

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

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

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

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

这解决了这个问题:

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

我没有用fork测试过,但是在一个用于调用100次的内部它可以工作。

种子与pid号码。 这有点但很难解决问题。

这是在一些页面:“这工作srand(time(0)+ getpid());但我不得不在案例0即子进程”中调用它。