什么是种子srand()的最佳方法?

9

我学习的方法是使用srand(time(NULL))初始化随机数生成器,然后使用rand()调用来生成随机数。但这种方法的问题在于,如果我在同一秒钟内多次运行程序,则生成的随机数将始终相同。有什么好的解决方法吗?


你可以采用系统特定的方法来获得更高的精确度。例如,Windows有GetTickCount。*nix有clock_gettime - chris
你的标题和问题内容在询问两件不同的事情。 - Pubby
不要连续快速运行程序?获取更精确的计时器? - Jeff Mercado
2
你可以混合多个信息源作为随机种子。例如,stime(time(NULL) * getpid()) 就可以达到目的。 - Havenard
2
XOR可能不太好,因为pid通常在每次运行时增加1,如果时间也增加1,很容易得到相同的结果。 - R.. GitHub STOP HELPING ICE
显示剩余2条评论
5个回答

6
在POSIX系统中,使用clock_gettime来获取当前时间的纳秒表示。如果您不需要很多比特数,可以忽略PRNG,直接使用时间的低位作为您的随机数。 :-)

我猜有人不喜欢我的使用当前时间的低位作为随机数生成器的想法。然而,考虑到这些因素会影响它们(内存延迟,缓存命中/失误,TLB失误,交换,中断定时,调度等),以及纳秒大致对应于现代计算机上的周期,它们是相当好的熵源。 - R.. GitHub STOP HELPING ICE
我同意。这既巧妙又优雅。因此我的问题就来了。我对于针对手头问题给出如此合适的答案被踩票感到困惑。这个解决方案几乎完美地解决了问题(在同一秒内多次运行程序并每次都得到相同的结果)。 - Jean

2
如果使用*nix系统,为什么不直接从/dev/random读取随机数呢?
此外,您可以从其他设备(如键盘、鼠标或CPU温度)收集噪声。
您可以使用加速度计并从海浪中收集噪声。风也会产生噪声。
我相信Glib提供了一个函数g_random_int(),可以快速和可移植地生成等分布的随机数。
或者,您可以只读取/tmp中的临时文件编号,并使用该编号通过time.h函数来提供给srand(),或者读取/tmp中的一个文件内容。
您可以从/usr/bin/中读取每个文件,并收集一些内容为srand()提供数据。

2
先生 -1,我期待阅读原因。 - yeyo

1
除了使用时间,另一种常见的为rand函数提供种子的方法是使用程序的进程ID,因为这是保证唯一的。
实际代码取决于平台,但如果你在Windows上,我相信你可以使用函数GetCurrentProcessId(),例如:
srand(GetCurrentProcessId());

3
以这种方式,每次调用“rand”函数时,您将获得相同的随机数序列。 - prehistoricpenguin
@prehistoricpenguin 你是什么意思? - Matt
2
@prehistoricpenguin,只有当您的进程每次具有相同的PID时才有效。这就是为什么将其与时间函数混合使用是一个好主意的原因。 - chris

1
int pid ; // get it as per your OS
timeval t;
gettimeofday(&t, NULL);
srand(t.tv_usec * t.tv_sec * pid);

time函数的返回值是以为单位的。而gettimeofday函数则是以微秒为单位的,这意味着种子出现重复的可能性更小了。另外,还使用了当前进程的ID。


t.tv_usec * t.tv_sec * pid 这个选择不够理想。当传递给 srand(unsigned) 时,该乘积会被转换为 unsigned 类型。3个数的乘积中的每个2的幂值都会减少种子可用的位数。相反,应该使用 ^ 运算符:t.tv_usec ^ t.tv_sec ^ pid - undefined

-2
除了输入时间外,您还可以将CPU时间添加到其中,我相信可以使用clock()来实现。 因此,它看起来像这样:srand(time() + clock())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接