【问题标题】:Questions with using boost for generating normal random numbers使用 boost 生成正常随机数的问题
【发布时间】:2012-08-12 00:14:40
【问题描述】:

当我看到This Post 时,我希望学习如何在 C++ 中从正态分布生成数字。它给出了一个很好的例子,但我仍然不确定boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > var_nor(rng, nd); 中的& 是什么意思。如果我这里没有包含这个&,会产生什么影响?

另外,在阅读Boost's official website上的教程时,我发现用boost::random::uniform_int_distribution<> dist(1, 6)生成分布对象后,他们可以通过调用dist(gen)直接生成随机数(这里的gen是随机引擎) ,而不调用“variate_generator”对象。当然,这是为了生成均匀的随机数,但我很好奇我是否可以对正态分布做同样的事情,作为调用“variate_generator”的另一种方法?

【问题讨论】:

    标签: c++ boost distribution


    【解决方案1】:

    简短的背景信息

    生成具有特定分布的随机数的一种方法是,例如,从区间 [0, 1) 生成均匀分布的随机数,然后对这些数字应用一些数学运算以将它们塑造成所需的分布。所以你有两个对象:一个来自 [0, 1) 的随机数生成器和一个分布对象,它 获取均匀分布的随机数并以所需的(例如正态)分布吐出随机数。

    为什么要通过引用传递生成器

    代码中的var_nor 对象将生成器rnd 与正态分布nd 耦合在一起。您必须通过引用传递您的生成器,即模板参数中的&。这真的很重要,因为随机数生成器有一个内部状态,它可以从中计算下一个(伪)随机数。如果您不通过引用传递生成器,您将创建它的副本,这可能会导致代码始终创建相同的随机数。以this blog post 为例。

    为什么需要variate_generator

    现在到了部分,为什么不直接使用生成器的发行版。如果您尝试以下代码

    #include <boost/random/mersenne_twister.hpp>
    #include <boost/random/normal_distribution.hpp>
    #include <iostream>
    
    int main()
    {
        boost::mt19937 generator;    
        boost::normal_distribution<> distribution(0.0, 1.0);
    
        // WARNING: THIS DOES NOT WORK AS MIGHT BE EXPECTED!!
        for (int i = 0; i < 100; ++i)
            std::cout << distribution(generator) << std::endl;
        return 0;
    }
    

    你会看到,它只输出NaNs(我已经用 Boost 1.46 测试过它)。原因是 Mersenne twister 返回一个均匀分布的 整数 随机数。但是,大多数(甚至可能是所有)连续分布都需要 [0, 1) 范围内的 浮点 随机数。 Boost 文档中给出的示例有效,因为 uniform_int_distribution 是一个离散分布,因此可以处理整数 RNG。

    注意:我没有尝试过使用较新版本的 Boost 的代码。当然,如果将离散RNG与连续分布一起使用,编译器会报错就好了。

    【讨论】:

    • 感谢 Mehrwolf 提供有用的背景信息!只是好奇,为什么原始帖子(以及您在此处的答案)没有在boost::normal_distribution&lt;&gt; distribution(0.0, 1.0) 中指定任何类型名?如果我把它写成boost::normal_distribution&lt;double&gt; distribution(0.0, 1.0),会有什么不同吗? (实际上我很困惑为什么你的使用在这里是合法的,基于我对类模板的了解非常有限......)
    • 经过一番谷歌搜索后,我想我明白了。在分发对象的类模板定义中使用= 指定了一个默认类型名(即template&lt;class RealType = double&gt;)。所以double在这里设置为默认类型名。
    • 正确。 double 是默认类型。
    猜你喜欢
    • 2011-05-18
    • 2011-01-16
    • 2023-04-02
    • 1970-01-01
    • 2016-05-26
    • 2013-06-03
    • 1970-01-01
    • 2017-04-10
    • 2014-07-20
    相关资源
    最近更新 更多