为什么 boost 的随机数生成(在正态分布上)总是给出相同的值?

Why is boost's random number generation (on a normal distribution) always giving the same values?

本文关键字:随机数 boost 正态分布 为什么      更新时间:2023-10-16

我正在做一些随机数生成和得到可疑的行为。下面是我的代码:

    // initialized earlier... in the constructor of a class
    boost::mt19937 *rng = new boost::mt19937();
    rng->seed(time(NULL));
    // actual use here.
    for (int i = 0; i < 10; ++i)
    {
        test();
    }

    void test()
    {
       boost::normal_distribution<> distribution(10, 10);
       boost::variate_generator< boost::mt19937, boost::normal_distribution<> > resampler(*rng, distribution);
       const double sample = (resampler)(); // always the same value.
    }

我误用了boost中的随机抽样吗?我做错了什么,让它总是相同的值。我在构造函数中初始化随机数生成器,因此它应该总是吐出一个不同的值(不被重新初始化)

问题出在boost::variate_generator< boost::mt19937, boost::normal_distribution<> > resampler(*rng, distribution);行。这个构造函数按值接受参数(参见文档)。因此,每个resampler从生成器的一个相同副本开始,并调用它一次。


编辑:Shafik注意到同样的事情就在我做了一点之后。如果您确实不能将初始化提升到循环之外,您也可以重新播种生成器。根据您的应用程序,有许多方法可以实现这一点。下面只是一个例子:

void test()
{
   static unsigned int seed = 0
   rng->seed((++seed) + time(NULL));
   boost::normal_distribution<> distribution(10, 10);
   boost::variate_generator< boost::mt19937, boost::normal_distribution<> > resampler(*rng, distribution);
   const double sample = (resampler)(); // always the same value.
}

注意:不要用time(NULL)重新播种rng,因为如果你在一个紧密的循环中调用test(),可能会返回相同的值几次。

这是因为您正在实例化函数test中的类,如果您将它们移到外面,则它按预期工作。您使用相同的生成器启动每个实例。请看这个最小的例子:

int main()
{
    boost::mt19937 *rng2 = new boost::mt19937();
    rng2->seed(time(NULL));
    boost::normal_distribution<> distribution(0, 1);
    boost::variate_generator< boost::mt19937, boost::normal_distribution<> >        resampler(*rng2, distribution);
    for (int i = 0; i < 10; ++i)
    {
        std::cout << resampler() << std::endl ;
    }
}

如果你改变循环工作像你发布的代码,那么你会看到同样的问题:

    for (int i = 0; i < 10; ++i)
    {
        boost::normal_distribution<> distribution(0, 1);
        boost::variate_generator< boost::mt19937, boost::normal_distribution<> >        resampler(*rng2, distribution);
        std::cout << resampler() << std::endl ;
    }

"为什么"已经在其他答案中解决了。下面是如何在不重新播种的情况下修复它(这破坏了使用生成器的意义):将normal_distributionvariate_generatormt19937一起初始化一次。

在你的类中,注意按适当的顺序定义这些成员。

作为旁注,'new'是没有用的,你可以简单地写:

boost::mt19937 rng ;