日記
C++11での乱数
世間はエイプリルフールで賑わっていますが、当サイトは特に何もないのです……。
いつも、4月1日になってから何か用意しとけば良かったなぁと思うんですけど、1年経ったら忘れてるんですよねぇ。不思議。
cocos2d-x v3.0からはC++11を使うようになりました。
auto型とかラムダ式とか色々と便利なものが使えるようになりましたが、その中の1つに乱数があります。
C言語のrand()が色々と残念な感じなのは言わずもがな、共通認識だと思いますが、C++11ではそれに代わる乱数ライブラリが追加されました。
話題としてはちょっと古いし今更話題にするようなことでもないような気がしますが、最近C++を勉強し出した初心者の中には知らない人も多そうな気がしたので(私とか)
C++11で使える乱数 – メルセンヌ・ツイスター法 (`・ω・´)シャキーン | わくわくとおーぼえ
C++11 の乱数ライブラリ <random> – Siv3D 開発ブログ
↑を参考にさせて頂きました。他にもググるとたくさん情報出てきます。
使い方としては、まず
std::random_deviceクラスのインスタンスを用意します。
このクラスは、外部デバイスとかの情報を元に乱数を生成するらしいです。
機械的な計算だけに基づくものではないので、予測不能な乱数を得られるとか何とか。
その分、処理が遅いので、最初の乱数のシードに使います。
処理速度をあまり気にしないアクション性のないものならこれだけでもいいかも。
std::mt19937はメルセンヌ・ツイスター法で乱数を生成します。
これにstd::random_deviceで得られた乱数をシードとして初期化します。
これで乱数を生成できるのですが、乱数を使う時って普通は特定の範囲内の数値が欲しいですよね。
std::uniform_int_distributionやstd::uniform_real_distribution等を使います。
これらは、乱数を元に指定した範囲内の値を返してくれます。
上記の2つは一様分布の整数と一様分布の浮動小数点数です。
他にも正規分布とかで偏った値を得られるものがあるようです。
rand()と比べて、ちょっと使い方がめんどいんで、私は↓みたいな感じで使ってます。
#include <random> static std::mt19937 _mt; void initRand(){ std::random_device rndDev; _mt = std::mt19937(rndDev()); } int getRand(int min, int max){ std::uniform_int_distribution<int> dist(min, max); return dist(_mt); } double getRand(double min, double max){ std::uniform_real_distribution<double> dist(min, max); return dist(_mt); }
乱数のシードの部分で、std::random_deviceを複数使って、よりランダム性を高くすることができるそうです。
1個でも、rand()使うよりは遥かにマシになったので、とりあえずこれでOKってことで。
2014/04/01