64位随机发生器的种子

我目前正在运行一个带有8个以上管道(线程)的multithreading仿真应用程序。 这些管道运行非常复杂的代码,该代码依赖于种子生成的随机序列。 然后将序列归结为单个0/1。

在将种子从主线程传递到处理管道之后,我希望这种“随机处理”是100%确定性的。 所以,我可以在第二次运行中复制结果。

所以,例如:(我有这个编码,它的工作原理)

Pipe 1 -> Seed: 123 -> Result: 0 Pipe 2 -> Seed: 123 -> Result: 0 Pipe 3 -> Seed: 589 -> Result: 1 

当我需要运行100M或更多这些过程然后平均结果时,就会出现问题。 可能只有100M中的1个是1,其余的都是0.很明显,我不能用32bit种子为srand() 100M随机值。

是否可以使用VS2010中的64位种子播种srand(),或使用等效方法?

rand()在2 ^ 32之后重复自身还是没有(有一些内部隐藏状态)?

谢谢

您可以使用C ++ 11的随机工具生成给定大小和种子大小的随机数,尽管此过程有点过于复杂,无法在此汇总。

例如,您可以构造一个std::mersenne_twister并使用64位整数播种,然后获取指定分布中的随机数,这似乎是您正在寻找的。

一个简单的64位LCG应该满足您的需求。 LCG的位n(从最低位作为位1计数)最多具有周期(并且,如果参数选择正确,则精确地)2 ^ n,因此如果不需要它们,请避免使用低位,以及/或在输出上使用回火function。 在我对另一个问题的回答中可以找到一个示例实现:

https://stackoverflow.com/a/19083740/379897

转贴:

 static uint32_t temper(uint32_t x) { x ^= x>>11; x ^= x<<7 & 0x9D2C5680; x ^= x<<15 & 0xEFC60000; x ^= x>>18; return x; } uint32_t lcg64_temper(uint64_t *seed) { *seed = 6364136223846793005ULL * *seed + 1; return temper(*seed >> 32); } 

你可以使用XOR SHIFT伪随机数生成器

它很快并且有效 – 这是我的实现类中的实际生成部分。 我在维基百科搜索psuedorandom数字生成器上找到了关于这个算法的信息……

 uint64_t XRS_64::generate(void) { seed ^= seed >> 12; // a seed ^= seed << 25; // b seed ^= seed >> 27; // c return seed * UINT64_C(2685821657736338717); } 

它很快,并且在初始化时你可以在构造函数中完成

 XRS_64::XRS_64() { seed = 6394358446697381921; } 

seed是一个unsigned int 64位变量,它在类中声明。

 class XRS_64 { public: XRS_64(); ~XRS_64(); void init(uint64_t newseed); uint64_t generate(); private : uint64_t seed; /* The state must be seeded with a nonzero value. */ }; 

我无法回答你的问题,但如果你发现你不能做你想做的事,你可以实现自己的伪随机算法生成器 ,它将uint64_t作为种子。 如果你想要一些更严肃的发生器(例如用于加密目的),有更好的算法用于此目的,但LCG是我看到的最容易实现的。

编辑

实际上你不能使用64位种子作为rand()函数。 你必须自己去。 在这个维基百科表中,MMIX Donald Knuth使用了一些参数来实现它。 请注意,根据您使用的参数,随机数生成器周期的值将小于2 ^ 64,并且由于乘法,您可能需要一个大数字库来处理数学运算。