64位随机发生器的种子

时间:2013-11-01 19:53:45

标签: c++ c visual-studio-2010 64-bit srand

我目前正在运行一个包含8个以上管道(线程)的多线程模拟应用程序。这些管道运行非常复杂的代码,该代码依赖于种子生成的随机序列。然后将序列归结为单个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。 很明显,我不能用32位种子对srand()进行100M随机值的采样。

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

rand()是否在2 ^ 32之后重复或不重复(有一些内部隐藏状态)?

由于

4 个答案:

答案 0 :(得分:3)

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

例如,您可以构造一个std::mersenne_twister<uint64_t, ...>并使用64位整数对其进行种子设定,然后获取指定分布中的随机数,这似乎就是您要查找的内容。

答案 1 :(得分:3)

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

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);
}

答案 2 :(得分:2)

您可以使用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. */
};

答案 3 :(得分:0)

我无法回答你的问题,但是如果你发现自己无法做到你想做的事,你可以实现自己的pseudo-random algorithm generator,其中uint64_t为种子。 如果你想要一些更严肃的生成器(例如用于加密目的),有更好的算法用于此目的,但LCG是我见过的最容易实现的。

修改

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