即使有种子,C ++ <random>分布也不是随机的

时间:2019-02-25 23:15:00

标签: c++ random

我想在main函数之外生成随机数,但是即使使用库并为随机数生成器设置种子,输出也不是随机的。任何帮助表示赞赏。

#include <iostream>
#include <random>
#include <time.h>

int foo(std::mt19937 rng)
{
    std::uniform_int_distribution<int> distr(0, 9);

    return distr(rng);
}

int main()
{
    std::random_device rd;
    std::mt19937 rng(rd());

    for (int j=0; j<10; j++)
    {
        std::cout << foo(rng) << " ";
    }
    return 0;
}

有输出

5 5 5 5 5 5 5 5 5 5

2 个答案:

答案 0 :(得分:7)

int foo(std::mt19937 rng)

您正在按值传递std :: mt19937生成器,因此当您将生成器传递给函数时,它不会从主函数中获取数字,因此将创建副本该生成器,只能在该函数内部进行修改,而不会影响main中的那个生成器。

您应该通过引用传递它,以便它修改main中的一个,并且在每次调用中,生成器都会创建不同的数字:

int foo(std::mt19937& rng)

答案 1 :(得分:3)

简短版本:更改foo以用作参考。

int foo(std::mt19937& rng);

当函数参数是对象类型而不是引用时,该参数是与传递给它的参数对象不同的对象。在这里,由于参数类型和参数类型相同,因此您使用的是复制构造函数。

将类似mt19937的熵源传递到类似uniform_int_distribution的分布时,分布的operator()称为熵源的operator()。熵源的operator()既返回伪随机值,又修改了熵源,以便其下一次调用将不同。

但是回到您的main中,原始对象rng尚未与发行版一起使用。它仅被复制,然后使用该副本。因此,下一次遍历循环时,将制作rng的另一个副本。但是,由于这个新对象与未使用的rng对象本质上相同,因此,一旦使用它只会再次产生相同的结果。

引用参数将解决所有问题,因为引用只是原始mt19937对象的另一个名称,因此实际上每次对foo的调用都在使用和更改原始对象。