题
我在 Unix 系统上使用 srandom() 和 random() 在 c 中生成随机数。我想要多个 RNG。给定相同的种子,每个都应该输出相同的序列。我还想保存并恢复每一个的状态。这是一个伪代码示例:
R1 = new_rng(5); //5 is the seed
R2 = new rng(5); //5 is the seed here, too.
a = R1.random();
b = R1.random();
d = R2.random(); //a == d
s1 = R2.get_state(); //save the state of R2
e = R2.random(); //b == e
R2.set_state(s1); //restore the state of R2
f = R2.random(); //b == f
我该怎么做呢?有时,RNG 会分叉到不同的线程中,我也需要在创建新线程时复制 RNG 的状态。
解决方案
使用 erand48()
/ nrand48()
/ jrand48()
以产生双精度浮点,非负长整数或符号长整型随机数,分别。这些功能让你有尽可能多的独立序列所需;状态被传递作为参数,并可以很容易地保存和恢复。此外,该序列是由标准定义,并且跨越运行不会发生变化,甚至在不同的平台。
一些其他的答案提示 rand_r()
。此功能是过时在POSIX.1-2008,其中包含本说明:
在
drand48()
函数提供了更复杂的随机数发生器。上可以一个函数调用之间并进行另一意味着
rand_r()
功能永远不能满足所有的上一个伪随机数发生器的要求的方式来实现的状态的量的限制。因此应避免使用此功能,每当非平凡要求(包括安全)已被满足。在
rand_r()
功能可能在将来的版本中删除。
其他提示
有一些针对各种 UNIX 风格的 C 库扩展:
- BSD 喜欢随机,检查 initstate/setstate
- _r 变体(random_r、srandom_r、initstate_r 等)
- rand_r(stdlib.h)
您的目标 UNIX 支持哪种风格?
使用rand_r(unsigned *seed)
代替srand()
和rand()
。这样,你可以保持多个随机种子。
我不知道,你可以依靠你的PRNG产生实际给予相同的种子完全相同的序列。我知道一些方法工作的方式,但我相信,一些更好的包括一定量的非确定性,使相同的种子可能会导致不同的序列。你必须通过你的libc文档用细齿梳,看看这是什么地方提及。如果没有,检查代码(如果你很幸运,有机会获得的代码)。
在任何情况下,这将耦合你的应用程序非常紧密的确在libc中的RNG实现。你一定会被绑定到libc的你正在开发上的味道,甚至可能libc的版本。如果此功能是非常重要的,你可能要重新实现在你的应用程序,以确保便携性和再现性的随机数生成。