c++で正規分布に従う乱数を発生させる

今回はc++で正規分布(ガウス分布)に従う乱数を発生させる方法についてです.

普段使いでは,ある範囲の乱数(0~1の間の値を発生させる乱数など)を生成することが多いのですが,
移動ロボットの世界では,センサからの情報を正規分布(ガウス分布)に従うノイズを伴った情報として近似することが多いので,
正規分布(ガウス分布)に従うノイズを発生させる手法をメモしておきます.

参考 : ガウス分布のグラフの概形を確認する

 

サンプルコード

平均0.0,標準偏差1.0の正規分布に従う乱数を1000000個生成して,
小領域に区切って,その領域内の乱数の個数をmatplotlib-cppを用いて表示するサンプルコードになります.
正規分布に従う乱数はrandomというヘッダファイルをインクルードすると使えるようになります.

 

 

コードの解説

擬似乱数を生成する

1行目で乱数のタネとなる乱数シードを生成するクラスのインスタンスを生成.
2行目では乱数シードから決定的な乱数を生成するクラスの初期化を行っています.

擬似乱数生成エンジンをざっと調べたところ,メルセンヌ・ツイスター法,線形合同法,キャリー付き減算法の3つの手法が実装されていました.
どのエンジンにどのような特徴があるのか,どのようなアルゴリズムで擬似乱数を生成しているのかまでは調べきれてはいませんが,初期シードから長周期の乱数列を高速に生成できるというメルセンヌ・ツイスター法が良さそうなので,今回はこちらを使用しています.

正規分布生成器を初期化する

この部分で平均mu,標準偏差sigを引数にとる正規分布生成器の初期化をおこなっています.
ロボットの分野では正規分布を表現する際にばらつき度合いは分散を用いますが,こちらの正規分布生成器の2つ目の引数は分散ではなく,標準偏差となっている点に注意が必要です.

 

残りの部分ではxの値を小領域に区切って,その範囲に存在している乱数の個数を数えています.
結果の描画にはmatplotlibを使用しています.
matplotlibはpythonのライブラリですが,なんとc++でも使用することができるんです.
以下の記事も参考にしてみてください.

c++でmatplotlibを使う | MY ROBOTICS

また,この正規分布に従う乱数はc++11以降のバージョンでの実装となりますので,コンパイルするときは以下のようにc++11のオプションをつけるのをお忘れなく.

 

 

実行結果

実行すると,こんな感じになります.
ちゃんと正規分布になっていますね.