C中的rand()函数即使在播种时也不是随机的

这很可能是机器相关的问题,但我无法弄清楚可能出现的问题。

#include  #include  #include  int main(int argc, char** argv) { srand(time(NULL)); int r1 = rand(); int r2 = rand(); printf("%d %d\n", r1, r2); } 

我使用编译上面的代码

 gcc randd.c 

然后手动运行几次,第一个数字看起来非常相似,而第二个看起来是随机的:

 1025720610 1435057801 1025737417 1717533050 1025754224 2000008299 1025771031 134999901 1025787838 417475150 

第一次调用rand()似乎与时间密切相关,并且随着时间的推移严格增加。 有关为何发生这种情况或如何解决的任何想法?

这发生在OSX 10.11上

  1. rand()非常糟糕,尽可能避免使用它。 在任何良好的RNG中,即使种子接近(汉明距离),第一个值也将与随机无法区分。 在rand事实并非如此。
  2. 如果你必须使用rand然后播种它,最好使用比时间更高的熵值,并多次调用rand()而不是重新播种 – 调用 – 重播。

例如2,考虑:

 #include  #include  #include  int main(int argc, char** argv) { int t=time(NULL); srand(t); for(int i=0; i < 10; i++) { float r = (float)rand()/(float)(RAND_MAX); printf("%f\n", r); } } 

结果如下:

 0.460600 0.310486 0.339473 0.519799 0.258825 0.072276 0.749423 0.552250 0.665374 0.939103 

它仍然是一个糟糕的RNG但是当你允许它使用内部状态而不是给它另一个类似的种子时,至少范围更好。

这正是您应该期待的。 没有“随机数”这样的东西。 只有具有随机分布的数字序列rand()函数生成这样的序列,但你没有给它机会,因为你不断重新播种它。 rand()生成的第一个数字很可能只是种子或种子本身的某些function。 一些rand()函数可能会对种子进行散列以隐藏它,但这并不能使它们更好,因为rand()的契约是产生一个随机序列

如果你需要一系列随机数来运行多个程序,你将不得不做类似的事情(a)编写一个调用srand()一次的程序,然后多次调用rand() ,让你的其他程序要求IPC上该程序的随机数; (b)使用像/dev/urandom这样的东西; (c)使用类似random.org东西。