c/Unix中的多个随机数生成器状态

c/Unix中的多个随机数生成器状态,c,unix,random,prng,C,Unix,Random,Prng,我使用srandom()和random()在Unix系统上用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

我使用srandom()和random()在Unix系统上用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的状态。

我不确定,如果有一个完全相同的种子,您能否依靠PRNG生成完全相同的序列。我知道有些方法是这样工作的,但我相信一些更好的方法包括一定数量的非决定论,因此一个相同的种子可能导致不同的序列。你必须仔细阅读你的libc文档,看看有没有提到这一点。如果没有,请检查代码(如果您有幸访问代码)


无论如何,这将使您的应用程序与libc中的PRNG实现紧密结合。你肯定会喜欢上你正在开发的libc,甚至可能是libc版本。如果此功能非常重要,您可能需要在应用程序中重新实现随机数生成,以确保可移植性和可复制性。

阅读。在最底层有几个实现的链接。(换句话说,自己实现一个PRNG。)

在各种UNIX风格上有一些C库扩展:

  • BSD类随机,检查初始状态/设置状态
  • _r变体(随机、随机、初始状态等)
  • 兰德公司(标准数据库h)
目标UNIX支持哪种风格?

使用
rand\u r(unsigned*seed)
而不是
srand()
rand()
。这样可以维护多个随机种子。

分别用于生成双精度浮点、非负长整数或有符号长整数随机数。这些函数允许您拥有所需的任意多个独立序列;状态作为参数传入,可以轻松保存和恢复。此外,序列由标准定义,即使在不同的平台上,也不会因运行而异

其他一些答案表明。此功能在POSIX.1-2008中已过时,其中包含以下注释:

drand48()
函数提供了一个更加复杂的随机数生成器

一个函数调用和另一个函数调用之间可以携带的状态量的限制意味着
rand_r()
函数的实现方式永远不能满足伪随机数生成器的所有要求。因此,当必须满足非琐碎要求(包括安全性)时,应避免此功能

rand\u r()
功能可能在将来的版本中被删除


“丑陋”的解决方案是创建一个类来保存种子和随机调用的次数,并使用它来恢复状态。当然,如果你使用了大量的数字,速度会非常慢。请看另一个答案,它说rand_r()不应该被使用(并给出了原因),没有办法。PNRG每次必须复制相同的序列。否则我们将如何重复调试测试。没有被破坏的PNRG。drand48()是这样的:新随机数=旧随机数*A+c看起来真的很弱!当然random()比这更强大。不,不是真的。许多“随机”实现类似于带进位生成器的乘法,或者类似于简单的LFSR;状态和算术为48位,结果取自状态的高位。如果您想要强度,那么您应该使用加密安全的随机数生成器。通常这会更慢,需要更多的存储来保存/恢复。OP对可重复性和保存/恢复能力更感兴趣。