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上
-
rand()
非常糟糕,尽可能避免使用它。 在任何良好的RNG中,即使种子接近(汉明距离),第一个值也将与随机无法区分。 在rand
事实并非如此。 - 如果你必须使用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
东西。