【问题标题】:C++ TR1: how to use the normal_distribution?C++ TR1:如何使用 normal_distribution?
【发布时间】:2010-11-10 05:57:46
【问题描述】:

我正在尝试使用 C++ STD TechnicalReport1 扩展来生成服从正态分布的数字,但是这段代码(改编自 this article):

mt19937 eng;
eng.seed(SEED);

normal_distribution<double> dist;
// XXX if I use the one below it exits the for loop
// uniform_int<int> dist(1, 52);

for (unsigned int i = 0; i < 1000; ++i) {
  cout << "Generating " << i << "-th value" << endl;
  cout << dist(eng) << endl;
}

只打印 1 条“正在生成...”日志消息,然后 永远不会退出 for 循环!如果我使用我注释掉的发行版,它会终止,所以我想知道我做错了什么。有什么想法吗?

非常感谢!

【问题讨论】:

    标签: c++ tr1 normal-distribution


    【解决方案1】:

    我在最初发布的代码中遇到了同样的问题,并调查了

    的 GNU 实现

    首先是一些观察: 使用 g++-4.4 并使用代码挂起, 使用 g++-4.5 并使用 -std=c++0x(即不是 TR1,而是真实的东西)上面的代码 works

    恕我直言,TR1 和 c++0x 在随机数生成和随机数消耗之间的适配器方面发生了变化——mt19937 产生整数,normal_distribution 消耗双精度数

    c++0x 自动使用适配,g++ TR1 代码没有

    为了让您的代码与 g++-4.4 和 TR1 一起使用,请执行以下操作

    std::tr1::mt19937 prng(seed);
    std::tr1::normal_distribution<double> normal;
    std::tr1::variate_generator<std::tr1::mt19937, std::tr1::normal_distribution<double> > randn(prng,normal);
    double r = randn();
    

    【讨论】:

      【解决方案2】:

      这绝对不会挂掉程序。但是,不确定它是否真的满足您的需求。

       #include <random>
       #include <iostream>
      
       using namespace std;
      
       typedef std::tr1::ranlux64_base_01 Myeng; 
      
       typedef std::tr1::normal_distribution<double> Mydist; 
      
       int main() 
       { 
            Myeng eng; 
            eng.seed(1000);
            Mydist dist(1,10); 
      
            dist.reset(); // discard any cached values 
            for (int i = 0; i < 10; i++)
            {
                 std::cout << "a random value == " << (int)dist(eng) << std::endl; 
            }
      
       return (0); 
       }
      

      【讨论】:

      • 谢谢,它的工作原理就像一个魅力,但我想知道为什么用这个引擎它可以工作,而不是另一个......
      • 显然,唯一的区别是您使用 mt19937 数字生成器,而 Jagannath 使用 std::tr1::ranlux64_base_01。从逻辑上讲,我猜这个错误可能存在于您的 mt19937 对象的实现中(我之前从未听说过的算法,谢谢 :-)),它不是 std 库的一部分。
      • 在绘制随机数时是否可以矢量化这样的for循环?我记得你不能向量化一个有函数调用的循环。
      【解决方案3】:

      如果您的 TR1 随机数生成实现有问题,您可以通过编写自己的普通生成器来避免 TR1,如下所示。

      使用您信任的任何随机生成器生成两个均匀 (0, 1) 随机样本 u 和 v。然后让 r = sqrt( -2 log(u) ) 并返回 x = r sin(2 pi v)。 (这称为 Box-Mueller 方法。)

      如果您需要具有平均 mu 和标准差 sigma 的正常样本样本,请返回 sigma*x + mu 而不仅仅是 x。

      【讨论】:

      • 刚刚试过这个。它运行速度超快——使用 100 万个样本进行了测试,它为 1-sigma、2-sigma 等范围内的样本提供了几乎完美的统计数据。
      【解决方案4】:

      虽然这似乎是一个错误,但快速确认是传递默认的 0.0、1.0 参数。 normal_distribution&lt;double&gt;::normal_distribution() 应该等于 normal_distribution&lt;double&gt;::normal_distribution(0.0, 1.0)

      【讨论】:

      • 它也不起作用,它仍然卡在执行第一个计算..
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      相关资源
      最近更新 更多