C++でプログラミングをする際、指定した範囲内での乱数が欲しい場面があります。今回はC++のSTLを利用して指定した範囲内での整数乱数を取得する方法を紹介します。
STLを使わない方法
C言語などのようにライブラリを用いない方法で範囲指定した乱数を生成する方法を知りたい方は以下をご覧ください。
STLを使う方法
C++11からSTLにrandomというライブラリが導入されました。これを用いることにより様々な種類の乱数生成が可能です。
ちなみに、本記事で紹介するコードは実装例の1つを挙げてライブラリの使い方を解説するためのものであり、これをすべての状況でコピペして使いまわすことを推奨するものではありません。使い方を理解した上で、ご自分の状況に合わせた実装をしてください。
乱数を生成する方法
std::mt19937
または std::mt19937_64
というクラスを用いることで、 質の良い擬似乱数で動作も高速と言われるメルセンヌ・ツイスタを用いた乱数を生成することができます。どちらを使うかは環境が64bitに対応しているかどうかで判断してください。
#include <random>
// 64bit環境の場合
uint64_t get_rand() {
// 乱数生成器(引数にシードを指定可能)
static std::mt19937_64 mt64(0);
// [0, (2^64)-1] の一様分布整数を生成
return mt64();
}
// 32bit環境の場合
uint32_t get_rand() {
// 乱数生成器(引数にシードを指定可能)
static std::mt19937 mt32(0);
// [0, (2^32)-1] の一様分布整数を生成
return mt32();
}
オブジェクトをstaticにしているのは、C言語標準のrand関数に似た使い勝手の関数を意識して実装したというだけで、必須ではありません。
範囲や分布を指定した乱数を生成する方法
上記で説明した乱数生成器を以下のように分布生成器に渡すことで、乱数の範囲を指定することができます。
#include <random>
uint64_t get_rand_range(uint64_t min_val, uint64_t max_val) {
// 乱数生成器
static std::mt19937_64 mt64(0);
// [min_val, max_val] の一様分布整数 (int) の分布生成器
std::uniform_int_distribution<uint64_t> get_rand_uni_int(min_val, max_val);
// 乱数を生成
return get_rand_uni_int(mt64);
}
また、分布生成器を以下で紹介するものに置き換えることで、値の型や分布の種類などを変えることができます。
ランダムな文字
aからzまでの範囲でランダムな文字が欲しければ以下のような分布生成器を使います。
// [a-z] の一様分布生成器
std::uniform_int_distribution<char> get_rand_uni_char('a', 'z');
0から1までの実数
整数ではなく0から1までの実数が必要な場合は以下のようにします。
// [0.0, 1.0) の一様分布実数生成器
std::uniform_real_distribution<double> get_rand_uni_real(0.0, 1.0);
正規分布
一様分布だけでなく、例えば正規分布などもあります。
// 平均0.0、標準偏差1.0の正規分布生成器
std::normal_distribution get_rand_norm_dist(0.0, 1.0)
その他詳しいことは random | cpprefjp - C++日本語リファレンス を参照ください。
まとめ
C++で範囲指定した乱数の生成方法を紹介しました。C言語と比較してC++のSTLがいかに便利で強力かがよくわかりますね。
C言語で範囲指定した乱数を生成する方法を知りたい方は以下をご覧ください。
余談
C言語を学んだ上でC++をさらに学びたいという人には以下の書籍がおすすめです。ただし昨今多い「わかりやすい」ような内容ではなく、詳しく正確な記述を重視しているものです。しっかりと気合いを入れて学びたいという人におすすめです。
以下はC++をある程度理解した人にとってC++11/14の機能を使ってより効率的なコードを書くためのTipsが学べる良い書籍です。基本的な入門書ではなくC/C++をある程度理解していることが必須です。