4

我正在做一些随机数生成并获得可疑行为。这是我的代码:

    // 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.
    }

我在提升中滥用随机抽样吗?我做错了什么以使其始终具有相同的价值。我在构造函数中初始化了随机数生成器,所以它应该总是吐出一个不同的值(没有重新初始化)

4

3 回答 3

8

问题出在线路上boost::variate_generator< boost::mt19937, boost::normal_distribution<> > resampler(*rng, distribution);。此构造函数按值获取其参数(请参阅文档)。因此,每个都resampler从生成器的相同副本开始并调用它一次。


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

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.
}

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

于 2013-04-01T16:37:56.497 回答
1

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 ;
    }
于 2013-04-01T16:38:30.890 回答
0

“为什么”已在其他答案中得到解决。以下是如何在不重新播种的情况下修复它(这破坏了使用生成器的意义):初始化normal_distributionvariate_generator一次,以及mt19937.

在您的班级中,请注意以正确的顺序定义这些成员。

作为旁注,“新”是没用的,你可以简单地写:

boost::mt19937 rng ;
于 2014-08-26T19:14:33.230 回答