C++ 创建具有均值和标准差的高斯随机生成器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19944111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:16:53  来源:igfitidea点击:

Creating a Gaussian Random Generator with a mean and standard deviation

c++randomgaussiannormal-distribution

提问by coder_For_Life22

I am trying to create a one dimensional array and use a random number generator(Gaussian generator that generates a random number with means of 70 and a standard deviation of 10) to populate the array with at least 100 numbers between 0 and 100 inclusive.

我正在尝试创建一个一维数组并使用随机数生成器(高斯生成器,它生成一个均值为 70 且标准差为 10 的随机数)来填充数组,其中至少包含 0 到 100 之间的 100 个数字。

How would i go about doing this in C++?

我将如何在C++ 中做到这一点?

回答by Shafik Yaghmour

In C++11this is relatively straight forward using the random headerand std::normal_distribution(live example):

C++11 中,使用随机标头std::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';
    }
}

If C++11is not an option than boostalso provides a library(live example):

如果C++11不是一个选项,那么boost还提供了一个库(现场示例):

#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';
  }
}

and if for some reason neither of these options is possible then you can roll your own Box-Muller transform, the code provided in the link looks reasonable.

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

回答by samad montazeri

Use the Box Muller distribution (from here):

使用 Box Muller 分布(来自此处):

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

you can read more at: wolframe math world

您可以在以下位置阅读更多信息:wolframe 数学世界

回答by Matteo Italia

In C++11 you would use the facilities provided by the <random>header; create a random engine (e.g. std::default_random_engineor std::mt19937, initialized with std::random_deviceif necessary) and a std::normal_distributionobject initialized with your parameters; then you can use them together to generate your numbers. Hereyou can find a full example.

在 C++11 中,您将使用<random>头文件提供的工具;创建一个随机引擎(例如std::default_random_enginestd::mt19937std::random_device必要时用 初始化)和一个std::normal_distribution用你的参数初始化的对象;然后你可以一起使用它们来生成你的数字。在这里你可以找到一个完整的例子。

In previous versions of C++, instead, all you have is the "classic" C LCG (srand/rand), which just generates a plain integer distribution in the range [0, MAX_RAND]; with it you can still generate gaussian random numbers using the Box-Muller transform. (It might be useful to note that the C++11 GNU GCC libstdc++'s std::normal_distributionuses the Marsaglia polar methodas shown herein.).

相反,在以前版本的 C++ 中,您所拥有的只是“经典的” C LCG ( srand/ rand),它只生成 [0, MAX_RAND] 范围内的普通整数分布;有了它,您仍然可以使用Box-Muller 变换生成高斯随机数。(注意 C++11 GNU GCC libstdc++std::normal_distribution使用这里显示的Marsaglia 极性方法可能很有用。)。

回答by yizzlez

With #include <random>

#include <random>

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