2

この投稿を見たとき、C++で正規分布から数値を生成する方法を学びたいと思っていました。これは非常に良い例ですが、それでもinが何&boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > var_nor(rng, nd);意味するのかわかりません。これをここに含めなかった場合、どのような効果があり&ますか?

また、 Boostの公式Webサイトのチュートリアルを読んだところ、で配布オブジェクトを生成した後、「variate_generator」オブジェクトを呼び出さなくても、(ここではgenはランダムエンジンです)を呼び出すことで、乱数boost::random::uniform_int_distribution<> dist(1, 6)を直接生成できることがわかりました。dist(gen)もちろん、これは均一な乱数を生成するためのものですが、「variate_generator」を呼び出す代わりの方法として、正規分布で同じことができるかどうか興味がありますか?

4

1 に答える 1

4

短い背景情報

特定の分布を持つ乱数を生成する1つのアプローチは、たとえば、区間[0、1)から一様分布の乱数を生成し、これらの数にいくつかの計算を適用して、目的の分布に整形することです。したがって、2つのオブジェクトがあります。1つは[0、1)からの乱数のジェネレーターで、もう1つは分散オブジェクトです。これは均一に分散された乱数を受け取り、目的の(正規などの)分布で乱数を吐き出します。

なぜジェネレータを参照で渡すのか

コード内のvar_norオブジェクトは、ジェネレーターrndを正規分布と結合しますnd&テンプレート引数にある参照を介してジェネレータを渡す必要があります。乱数ジェネレーターには、次の(疑似)乱数を計算する内部状態があるため、これは非常に重要です。ジェネレーターを参照経由で渡さない場合は、ジェネレーターのコピーを作成すると、コードが生成される可能性があり、常に同じ乱数が作成されます。例として、このブログ投稿を参照してください。

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

sのみを出力することがわかりますNaN(Boost 1.46でテストしました)。その理由は、メルセンヌツイスターが一様分布の整数乱数を返すためです。ただし、ほとんどの(おそらくすべての)連続分布では、範囲[0、1)の浮動小数点乱数が必要です。Boostのドキュメントに示されている例uniform_int_distributionは、離散分布であり、整数RNGを処理できるため機能します。

注:新しいバージョンのBoostでコードを試したことはありません。もちろん、離散RNGを連続配布と一緒に使用する場合、コンパイラーがエラーをスローすると便利です。

于 2012-08-11T16:14:40.580 に答える