C ++ 即使种子,分布也不是随机的

问题描述 投票:1回答:2

我想在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
c++ random
2个回答
7
投票
int foo(std::mt19937 rng)

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

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

int foo(std::mt19937& rng)

3
投票

简短版本:更改foo以获取参考。

int foo(std::mt19937& rng);

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

当像mt19937这样的熵源传递给像uniform_int_distribution这样的分布时,分布的operator()称为熵源的operator()。熵源的operator()都返回伪随机值并且还修改熵源以使其下一次调用不同。

但回到你的main,原始对象rng没有用于分发。它只被复制,然后使用该副本。因此,下次循环时,会制作另一份rng副本。但由于这个新鲜对象与未使用的rng对象基本相同,因此使用它只会再次产生相同的结果。

引用参数将修复所有这些,因为那时引用只是原始mt19937对象的另一个名称,因此每次调用foo实际上都在使用和更改原始对象。

© www.soinside.com 2019 - 2024. All rights reserved.