web-dev-qa-db-ja.com

平均と標準偏差を持つガウスランダムジェネレーターの作成

1次元配列を作成し、乱数ジェネレーター(70の平均と10の標準偏差で乱数を生成するガウスジェネレーター)を使用して、0から100までの少なくとも100の数値を配列に設定しようとしています。

C++でこれを行うにはどうすればよいですか?

16

C++ 11では、これは ランダムヘッダー および std :: normal_distribution を使用して比較的簡単です。 =(実例):

#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も提供しますライブラリ(実例):

#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変換 をロールできます。リンクで提供されるコードは妥当なように見えます。

27
Shafik Yaghmour

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 をご覧ください。

9
samad montazeri

C++ 11では、<random>ヘッダーによって提供される機能を使用します。ランダムエンジン(たとえば、必要に応じてstd::default_random_engineで初期化されたstd::mt19937またはstd::random_device)と、パラメーターで初期化されたstd::normal_distributionオブジェクトを作成します。次に、それらを一緒に使用して番号を生成できます。 ここ で完全な例を見つけることができます。

C++の以前のバージョンでは、代わりに、「クラシック」なC LCG(srand/Rand)のみが存在し、範囲[0、MAX_Rand]の単純な整数分布を生成します。これにより、 Box-Muller変換 を使用してガウス乱数を生成できます。 (C++ 11 GNU GCC libstdc ++のstd::normal_distributionは、 Marsaglia polar method 示されているように herein 。)。

3
Matteo Italia

#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;
}
2
yizzlez