短い背景情報
特定の分布を持つ乱数を生成する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を連続配布と一緒に使用する場合、コンパイラーがエラーをスローすると便利です。