在多个函数中使用相同的随机数生成器

New*_*cks 3 c++ random global global-variables

我相信,随机数发生器(RNG)仅应播种一次,以确保结果的分配符合预期。

我正在用C ++写一个蒙特卡洛模拟,它由一个主要函数(“ A”)多次调用另一个函数(“ B”)组成,其中在B中生成了大量随机数。

目前,我正在B中执行以下操作:

void B(){
    std::array<int, std::mt19937::state_size> seed_data;
    std::random_device r;

    std::generate(seed_data.begin(), seed_data.end(), std::ref(r));
    std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); //perform warmup
    std::mt19937 eng(seq);

    std::uniform_real_distribution<> randU(0,1);

    double myRandNum = randU(eng);

    //do stuff with my random number
}
Run Code Online (Sandbox Code Playgroud)

如您所见,每次调用函数B时,我都会创建一个新的随机数生成器。据我所知,这是浪费时间-RNG仍然可以生成更多的随机数!

我已经尝试过使“ eng”成为extern,但是使用g ++会产生错误:

错误:“ eng”同时具有“ extern”和初始化程序extern std :: mt19937 eng(seq);

如何使随机数生成器成为“全局”,以便可以多次使用?

Dút*_*has 5

谨慎适用于所有规则。“全球是邪恶的”就是其中之一。RNG 应该是全局对象。(注意:每个线程都应该有自己的RNG!)我倾向于将我的代码包装在一个单例映射中,但是只需在开始时main()就播种并预热一个即可:

std::mt19937 rng;

int main()
{
  // (seed global object 'rng' here)
  rng.dispose(10000); // warm it up
Run Code Online (Sandbox Code Playgroud)

对于您的使用场景(每个调用生成多个RN),为每个函数调用创建本地分发都应该没有问题。

另一件事:std::random_device不是您的朋友- throw出于各种愚蠢的原因,它可以随时出现。确保将其包装在try.. catch块中。或者,我建议这样做,使用特定平台的方法来获取真实的随机数。(在Windows上,使用Crypto API。在其他所有上,使用/dev/urandom/。)

希望这可以帮助。

  • 使用 `seed()` 成员函数:`rng.seed(your_seed_sequence)`。 (2认同)
  • 为什么需要预热随机数生成器?我从来没有听说过预热发电机。 (2认同)