函数的随机整数总是返回相同的数字 - 为什么?

时间:2017-01-05 16:28:46

标签: c++ random stl

我目前正在学习C ++并对random_device有疑问。

我正试图模拟monty hall问题。为此我需要随机整数来随机选择门。因此,我尝试创建一个为此目的返回随机整数的函数。

int guessGetRandomIndex() {
    std::random_device rd; // obtain a random number from hardware
    std::mt19937 eng(rd()); // seed the generator
    std::uniform_int_distribution<> distr(0, 2);
    return distr(eng);

然而,当我尝试在main()中获得随机整数时,我会一直得到相同的数字。

    vector<int> v = {0, 1, 2, 3, 4, 5};
for (auto & j : v){
    int random = guessGetRandomIndex();
    std::cout << random << ' ';
}    
 Output: 1 1 1 1 1 etc.

然而,当我将随机设备放入主循环并执行相同操作时,我设法得到随机整数。

    std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<> distr(0, 2); // define the range
vector<int> v = {0, 1, 2, 3, 4, 5};
for (auto & j : v){

    std::cout << distr(eng) << ' ';
}   

 Output: 1 2 1 2 0 1

为什么?我只是试图封装随机设备。我认为每次调用与Pythons random.randint类似的函数时它会产生新的随机数,但我认为C ++中还有其他东西在进行。

提前致谢。

2 个答案:

答案 0 :(得分:7)

每次拨打std::random_device时,您都会创建新的std::mt19937guessGetRandomIndex生成器。将它们标记为static或通过引用将它们传递给函数以避免重新实例化它们:

int guessGetRandomIndex() {
    static std::random_device rd; // obtain a random number from hardware
    static std::mt19937 eng(rd()); // seed the generator
    std::uniform_int_distribution<> distr(0, 2);
    return distr(eng);
}

为了生成伪随机数,标准库提供的生成器包含的内部状态在每次生成值时都会发生变化。如果继续重新实例化生成器,内部状态将始终与其初始状态匹配,因此始终生成相同的数字。

答案 1 :(得分:2)

虽然不能保证每次都能得到相同的结果,但是你尝试做事的方式肯定是次优的(接近于完全错误)。特别是,至少在您显示代码时,每次要求提供其他号码时,您都会重新播种PRNG。你想要做的是播种一次,然后使用连续的数字而无需重新播种。

您可以通过在函数中将它们标记为static来解决此问题,或者(通常更好)使用类,在ctor中执行这些操作,并在成员函数中生成数字:

class RandomIndex {
    std::mt19937 eng;
    std::uniform_int_distribution<> distr;
public:
    guessGetRandomIndex(int lower, int upper) 
        : eng(std::random_device()())
        , distr(lower, upper)
    {}

    int operator()() { 
         return distr(eng);
    }
};

这是一个额外的代码,但不是很大的代码 - 它可以带来一些好处 1

使用它非常简单:

RandomIndex d(0, 2);

for (int i=0; i<10; i++)
    std::cout << d();

一个结果:

0 2 1 2 1 2 0 2 1 0

一个小问题:尽管这个特定的运行并没有显示单个数字的重复,但它确实包含的序列2 1比大多数人预期的要多。实际上,测试表明人们通常期望随机序列包含的重复次数(单个数字或如上所示的序列)要比随机发生的重复少得多。例如,大多数人会看一下像0 0 1 1 2 2这样的序列,并将其判断为从不(或几乎从不)随机发生的事情。实际上,它与具有相同参数的任何其他序列一样可能,因此如果您阻止它发生,您就减少随机性。

1.例如,具有静态功能的函数可能包含一些代码来检查是否已完成初始化,并且当且仅当先前没有完成时才执行此操作。 功能

相关问题