【问题标题】:Creating a Gaussian Random Generator with a mean and standard deviation创建具有均值和标准差的高斯随机发生器
【发布时间】:2013-11-25 11:36:14
【问题描述】:

我正在尝试创建一个一维数组并使用随机数生成器(生成平均值为 70 且标准差为 10 的随机数的高斯生成器)在数组中填充至少 100 个介于 0 和 100 之间的数字包括在内。

我将如何在 C++ 中执行此操作?

【问题讨论】:

    标签: c++ random gaussian normal-distribution


    【解决方案1】:

    C++11 中,使用 random headerstd::normal_distribution (live example) 相对简单:

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <map>
    #include <random>
    
    int main()
    {
        std::random_device rd;
    
        std::mt19937 e2(rd());
    
        std::normal_distribution<> dist(70, 10);
    
        std::map<int, int> hist;
        for (int n = 0; n < 100000; ++n) {
            ++hist[std::round(dist(e2))];
        }
    
        for (auto p : hist) {
            std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                      << p.first << ' ' << std::string(p.second/200, '*') << '\n';
        }
    }
    

    如果 C++11 不是一个选项,那么 boost 也提供了一个库(live example):

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <map>
    #include <random>
    #include <boost/random.hpp>
    #include <boost/random/normal_distribution.hpp>
    
    int main()
    {
    
      boost::mt19937 *rng = new boost::mt19937();
      rng->seed(time(NULL));
    
      boost::normal_distribution<> distribution(70, 10);
      boost::variate_generator< boost::mt19937, boost::normal_distribution<> > dist(*rng, distribution);
    
      std::map<int, int> hist;
      for (int n = 0; n < 100000; ++n) {
        ++hist[std::round(dist())];
      }
    
      for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
      }
    }
    

    如果由于某种原因这两个选项都不可行,那么您可以推出自己的Box-Muller transform,链接中提供的代码看起来很合理。

    【讨论】:

    • 感谢您的回答。我正在阅读您建议的第一个方法,我对最后两部分有点困惑,这最终意味着我看不到我们在哪里生成正态分布的数字。我们用std::map&lt;int, int&gt; hist;for (int n = 0; n &lt; 100000; ++n) {++hist[std::round(dist())];} 部分和for (auto p : hist) {... 部分实现了什么?提前致谢。
    • @user929304 dist 生成正常的随机变量...hist 是一组用于显示结果以查看高斯图的存储桶,查看实时示例可能会有所帮助。
    • 非常感谢您回复我。我正在玩现场示例,但仍在苦苦挣扎。简而言之,我正在尝试编写一个循环(即运行 10 次),在每次运行时我生成一个从具有 mean 0 和 variance的高斯分布中选择的数字> 0.05。我做了什么:std::random_device rd;std::mt19937 e2(rd());std::normal_distribution&lt;float&gt; dist(0, sqrt(0.05));for (int i=0; i&lt;10; i++){std::cout &lt;&lt; dist(e2) &lt;&lt; '\n';},它似乎工作但我不知道为什么我应该将e2传递给它?我知道rd 是这里的种子,但为什么我们需要e2
    【解决方案2】:

    使用 Box Muller 分布(来自here):

    double rand_normal(double mean, double stddev)
    {//Box muller method
        static double n2 = 0.0;
        static int n2_cached = 0;
        if (!n2_cached)
        {
            double x, y, r;
            do
            {
                x = 2.0*rand()/RAND_MAX - 1;
                y = 2.0*rand()/RAND_MAX - 1;
    
                r = x*x + y*y;
            }
            while (r == 0.0 || r > 1.0);
            {
                double d = sqrt(-2.0*log(r)/r);
                double n1 = x*d;
                n2 = y*d;
                double result = n1*stddev + mean;
                n2_cached = 1;
                return result;
            }
        }
        else
        {
            n2_cached = 0;
            return n2*stddev + mean;
        }
    }
    

    您可以阅读更多内容:wolframe math world

    【讨论】:

    • 你怎样才能让它在每次运行时都有一个随机输出?
    • @Wolfy 确实如此!注意rand() 内的rand_normal(double mean, double stddev) 函数。也许您在使用此功能之前缺少srand(time(NULL)),因此您总是得到相同的数字。
    【解决方案3】:

    在 C++11 中,您将使用 &lt;random&gt; 标头提供的功能;创建一个随机引擎(例如std::default_random_enginestd::mt19937,必要时使用std::random_device 初始化)和一个使用您的参数初始化的std::normal_distribution 对象;然后你可以一起使用它们来生成你的数字。 Here你可以找到一个完整的例子。

    在以前的 C++ 版本中,您所拥有的只是“经典”C LCG (srand/rand),它只生成 [0, MAX_RAND] 范围内的普通整数分布;有了它,您仍然可以使用Box-Muller transform 生成高斯随机数。 (请注意,C++11 GNU GCC libstdc++ 的 std::normal_distribution 使用 Marsaglia polar method,如 herein 所示。)。

    【讨论】:

      【解决方案4】:

      #include &lt;random&gt;

      std::default_random_engine de(time(0)); //seed
      std::normal_distribution<int> nd(70, 10); //mean followed by stdiv
      int rarrary [101]; // [0, 100]
      for(int i = 0; i < 101; ++i){
          rarray[i] = nd(de); //Generate numbers;
      }
      

      【讨论】:

      • 现在,我得到错误:[错误]'default_random_engine'不是'std'的成员
      最近更新 更多