【问题标题】:Why is boost's random number generation (on a normal distribution) always giving the same values?为什么 boost 的随机数生成(在正态分布上)总是给出相同的值?
【发布时间】:2013-03-22 17:58:17
【问题描述】:

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

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

【问题讨论】:

  • 你总是得到什么价值?
  • @jeremy 该值取决于程序的运行,因为 RNG 是按时间播种的。但是,在该程序的执行中每次运行 test() 总是相同的。
  • time(NULL) 返回什么,种子期望什么?也许那个种子正在截断种子值

标签: c++ boost random


【解决方案1】:

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

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

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

boost::mt19937 rng ;

【讨论】:

    【解决方案2】:

    问题在于boost::variate_generator&lt; boost::mt19937, boost::normal_distribution&lt;&gt; &gt; resampler(*rng, distribution); 行。此构造函数按值获取其参数(请参阅the documentation)。所以每个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(),可能会多次返回相同的值。

    【讨论】:

      【解决方案3】:

      这是因为您在函数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 ;
          }
      

      【讨论】:

        猜你喜欢
        • 2022-01-17
        • 1970-01-01
        • 2011-05-26
        • 2020-11-25
        • 2011-06-25
        • 2019-06-14
        • 1970-01-01
        • 2018-06-22
        • 2014-11-06
        相关资源
        最近更新 更多