擬似乱数生成
乱数ライブラリは乱数および擬似乱数を生成するクラスを提供します。 これらのクラスには以下のようなものがあります。
- 一様ランダムビットジェネレータ (Uniform random bit generator; URBG)。 一様分布の整数シーケンスを生成する擬似乱数ジェネレータと、利用可能であれば真の乱数ジェネレータの、両方が含まれます。
- 乱数分布 (一様分布、正規分布、 ポアソン分布など)。 URBG の出力を様々な統計的分布に変換します。
URBG と分布は乱数値を生成するために一緒に使用するように設計されています。 すべての乱数エンジンは、同じシミュレーションを繰り返せるように、明示的にシードされ、シリアライズされ、デシリアライズされることができます。
目次 |
[編集] 一様ランダムビットジェネレータ
一様ランダムビットジェネレータは有り得る結果の範囲内のそれぞれの値の返される確率が (理想的には) 等しいような符号なし整数値を返す関数オブジェクトです。
すべての一様ランダムビットジェネレータは UniformRandomBitGenerator の要件を満たします。 C++20 では uniform_random_bit_generator コンセプトも定義されます。
ヘッダ
<random> で定義 | |
(C++20) |
型が一様ランダムビットジェネレータとして適格であることを指定します (コンセプト) |
[編集] 乱数エンジン
乱数エンジンはシードデータをエントロピーソースとして使用して擬似乱数を生成します。 いくつかの異なる擬似乱数生成アルゴリズムのクラスがカスタマイズ可能なテンプレートとして実装されます。
使用するエンジンの選択にはいくつかのトレードオフがあります。 線形合同法は適度に高速で、状態保持のために非常に小さな記憶域しか必要としません。 ラグ付きフィボナッチ法は高度な算術命令セットを持たないプロセッサでも非常に高速ですが、大きな状態記憶域を必要とし、時々あまり良くない分布特性を示すことがあります。 メルセンヌ・ツイスタはそれ��より低速で大きな状態記憶域が必要ですが、正しいパラメータを与えれば非常に長い周期と最も好ましい分布特性を持ちます。
ヘッダ
<random> で定義 | |
(C++11) |
線形合同法のアルゴリズムを実装します (クラステンプレート) |
(C++11) |
メルセンヌ・ツイスタのアルゴリズムを実装します (クラステンプレート) |
(C++11) |
キャリー付き減算 (ラグ付きフィボナッチ法) のアルゴリズムを実装します (クラステンプレート) |
[編集] 乱数エンジンアダプタ
乱数エンジンアダプタは他の乱数エンジンをエントロピーソースとして使用して擬似乱数を生成します。 これらは一般的に基になるエンジンの分布特性を変更するために使われます。
ヘッダ
<random> で定義 | |
(C++11) |
乱数エンジンの出力をいくらか破棄します (クラステンプレート) |
(C++11) |
指定されたビット数のブロックに乱数の出力をパックします (クラステンプレート) |
(C++11) |
乱数エンジンの出力を異なる順序に並び替えます (クラステンプレート) |
[編集] 定義済みの乱数生成エンジン
ポピュラーなアルゴリズムがいくつか具体的に定義されています。
ヘッダ
<random> で定義 | |
型 | 定義 |
minstd_rand0 (C++11)
|
std::linear_congruential_engine<std::uint_fast32_t, 16807, 0, 2147483647> Lewis、 Goodman および Miller によって1969年に発見され、 Park と Miller によって1988年に「最低基準」として選定されたもの |
minstd_rand (C++11)
|
std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647> Park、 Miller および Stockmeyer によって1993年に推奨された新たな「最低基準」 |
mt19937 (C++11)
|
std::mersenne_twister_engine<std::uint_fast32_t, 32, 624, 397, 31, |
mt19937_64 (C++11)
|
std::mersenne_twister_engine<std::uint_fast64_t, 64, 312, 156, 31, |
ranlux24_base (C++11)
|
std::subtract_with_carry_engine<std::uint_fast32_t, 24, 10, 24> |
ranlux48_base (C++11)
|
std::subtract_with_carry_engine<std::uint_fast64_t, 48, 5, 12> |
ranlux24 (C++11)
|
std::discard_block_engine<std::ranlux24_base, 223, 23> Martin Lüscher と Fred James による24ビットの RANLUX ジェネレータ (1994年) |
ranlux48 (C++11)
|
std::discard_block_engine<std::ranlux48_base, 389, 11> Martin Lüscher と Fred James による48ビットの RANLUX ジェネレータ (1994年) |
knuth_b (C++11)
|
std::shuffle_order_engine<std::minstd_rand0, 256> |
default_random_engine (C++11)
|
処理系定義 |
[編集] 非決定的な乱数
std::random_device は非決定的な一様ランダムビットジェネレータです。 処理系に非決定的な乱数生成のサポートがない場合は擬似乱数エンジンを使用して実装されることがあります。
(C++11) |
ハードウェアエントロピーソースを使用する非決定的な乱数生成器 (クラス) |
[編集] 乱数分布
乱数分布は URBG の出力を後処理し、定義された統計的確率密度関数に従って分布させます。
乱数分布は RandomNumberDistribution を満たします。
ヘッダ
<random> で定義 | |
一様分布 | |
(C++11) |
範囲内に一様に分布した整数値を生成します (クラステンプレート) |
(C++11) |
範囲内に一様に分布した実数値を生成します (クラステンプレート) |
ベルヌーイ分布 | |
(C++11) |
ベルヌーイ分布に従った bool 値を生成します。 (クラス) |
(C++11) |
二項分布に従った整数値を生成します。 (クラステンプレート) |
負の二項分布に従った整数値を生成します。 (クラステンプレート) | |
(C++11) |
幾何分布に従った整数値を生成します。 (クラステンプレート) |
ポアソン分布 | |
(C++11) |
ポアソン分布に従った整数値を生成します。 (クラステンプレート) |
(C++11) |
指数分布に従った実数値を生成します。 (クラステンプレート) |
(C++11) |
ガンマ分布に従った実数値を生成します。 (クラステンプレート) |
(C++11) |
ワイブル分布に従った実数値を生成します。 (クラステンプレート) |
(C++11) |
極値分布に従った実数値を生成します。 (クラステンプレート) |
正規分布 | |
(C++11) |
標準正規 (ガウス) 分布に従った実数値を生成します。 (クラステンプレート) |
(C++11) |
対数正規分布に従った実数値を生成します。 (クラステンプレート) |
(C++11) |
カイ二乗分布に従った実数値を生成します。 (クラステンプレート) |
(C++11) |
コーシー分布に従った実数値を生成します。 (クラステンプレート) |
(C++11) |
フィッシャーのF分布に従った実数値を生成します。 (クラステンプレート) |
(C++11) |
スチューデントのt分布に従った実数値を生成します。 (クラステンプレート) |
標本分布 | |
(C++11) |
指定された離散分布に従ったランダムな整数を生成します。 (クラステンプレート) |
指定された区間に一定に分布する実数値を生成します。 (クラステンプレート) | |
指定された区間に線形に分布する実数値を生成します。 (クラステンプレート) |
[編集] ユーティリティ
ヘッダ
<random> で定義 | |
(C++11) |
[0, 1) 内に一様に分布した、与えられた精度における実数値 (関数テンプレート) |
(C++11) |
汎用のバイアス除去付きのスクランブルされたシードシーケンス生成器 (クラス) |
[編集] C の乱数ライブラリ
上で説明したエンジンと分布に加え、 C の乱数ライブラリの関数と定数も利用できますが、推奨されません。
ヘッダ
<cstdlib> で定義 | |
擬似乱数を生成します (関数) | |
擬似乱数ジェネレータをシードします (関数) | |
std::rand によって生成可能な最大値 (マクロ定数) |
[編集] 例
#include <iostream> #include <iomanip> #include <string> #include <map> #include <random> #include <cmath> int main() { // 利用可能であれば、本物の乱数値を用いてシードします。 std::random_device r; // 1から6の間のランダムな平均を選びます。 std::default_random_engine e1(r()); std::uniform_int_distribution<int> uniform_dist(1, 6); int mean = uniform_dist(e1); std::cout << "Randomly-chosen mean: " << mean << '\n'; // その平均を中心とする正規分布を生成します。 std::seed_seq seed2{r(), r(), r(), r(), r(), r(), r(), r()}; std::mt19937 e2(seed2); std::normal_distribution<> normal_dist(mean, 2); std::map<int, int> hist; for (int n = 0; n < 10000; ++n) { ++hist[std::round(normal_dist(e2))]; } std::cout << "Normal distribution around " << mean << ":\n"; for (auto p : hist) { std::cout << std::fixed << std::setprecision(1) << std::setw(2) << p.first << ' ' << std::string(p.second/200, '*') << '\n'; } }
出力例:
Randomly-chosen mean: 4 Normal distribution around 4: -4 -3 -2 -1 0 * 1 *** 2 ****** 3 ******** 4 ********* 5 ******** 6 ****** 7 *** 8 * 9 10 11 12
[編集] 関連項目
擬似乱数生成 の C言語リファレンス
|