メルセンヌツイスタの導入
億単位の解を生成するのに、rand()では力不足すぎる。というわけで、メルセンヌツイスタ(MT)を導入することにした。
MTをサポートするライブラリはいくつかあるが、初心者は最も使われているものを使え、ということで、boost::randomに含まれているものを使う。
導入は簡単で、boostのライブラリをDL、コンパイラのインクルードパスに追加すれば良い。使い方もドキュメントに載っている。のだが、使いたい関数内で初期化するのでは使い物にならない。別の関数に移動しても、同じシードの系列から発生してくれないと困る。ランダムな初期化シードを与えるのは非常に面倒なので、同じシードの乱数を平行して使われたりしたら困るのだ。それに、乱数の範囲ごとに発生器を作る必要があるのも、同様の理由で困る。
そこで、プログラムの最初に初期化して、どの関数からも呼び出せるようにしたい。また、乱数発生時に与えた数までを範囲とした一様乱数を戻すようにしたい。このときに与える数値がintであれば、整数を戻すようにしたい。というわけで、次のように書くことにした。
#include <boost/random.hpp> namespace math { static boost::mt19937 gen_(static_cast<unsigned long>(time(0))); static boost::uniform_real<> dst_(0,1); static boost::variate_generator<boost::mt19937, boost::uniform_real<> > rand_(gen_, dst_); static boost::uniform_real<>::result_type random() { return rand_(); }; template<class T> static T random(T n) { return static_cast<T>(rand_()*n);} };
[0,1)一様乱数から、定数倍して所望の範囲の乱数を得る。これは普通のrand()から作るときとほぼ同様である。これだけcommon.hなどに書いておけば、あまり中身を気にせずに乱数が使えるだろう。
もし複数の乱数発生器が欲しければ、別のnamespaceで作れば良いだろう。あるいは、必要を感じたら専用のクラスを作っても良い。