擬似乱数生成
乱数ライブラリは乱数および擬似乱数を生成するクラスを提供します。 これらのクラスには以下のようなものがあります。
- 乱数エンジン (一様分布の整数シーケンスを生成する擬似乱数と、利用可能であれば、真の乱数の、両方があります)
- 乱数分布 (乱数エンジンの出力を様々な統計的分布に変換します)
エンジンと分布は乱数値を生成するために一緒に使用するように設計されています。 すべてのエンジンは、同じシミュレーションを繰り返せるように、明示的にシードされ、シリアライズされ、デシリアライズされることができます。
目次 |
[編集]乱数エンジン
乱数エンジンはシードデータをエントロピーソースとして使用して擬似乱数を生成します。 いくつかの異なる擬似乱数生成アルゴリズムのクラスがカスタマイズ可能なテンプレートとして実装されます。
使用するエンジンの選択にはいくつかのトレードオフがあります。 線形合同法は適度に高速で、状態保持のために非常に小さな記憶域しか必要としません。 ラグ付きフィボナッチ法は高度な算術命令セットを持たないプロセッサでも非常に高速ですが、非常に大きな状態記憶域を必要とし、時々あまり良くない分布特性を示すことがあります。 メルセンヌツイスタはそれらより低速で大きな状態記憶域が必要ですが、正しいパラメータを与えれば非常に長い周期と最も好ましい分布特性を持ちます。
乱数エンジンは UniformRandomBitGenerator
を満たします。
ヘッダ <random> で定義 | |
(C++11) | 線形合同法のアルゴリズムを実装します (クラステンプレート) |
(C++11) | メルセンヌ・ツイスタのアルゴリズムを実装します (クラステンプレート) |
(C++11) | キャリー付き減算 (ラグ付きフィボナッチ法) のアルゴリズムを実装します (クラステンプレート) |
[編集]乱数エンジンアダプタ
乱数エンジンアダプタは他の乱数エンジンをエントロピーソースとして使用して擬似乱数を生成します。 これらは一般的に基になるエンジンの分布特性を変更するために使われます。
ヘッダ <random> で定義 | |
(C++11) | 乱数エンジンの出力をいくらか破棄します (クラステンプレート) |
(C++11) | 指定されたビット数のブロックに乱数の出力をパックします (クラステンプレート) |
(C++11) | 乱数エンジンの出力を異なる順序に並び替えます (クラステンプレート) |
[編集]定義済みの乱数生成エンジン
ポピュラーなアルゴリズムがいくつか具体的に定義されています。
ヘッダ <random> で定義 | |
型 | 定義 |
minstd_rand0 | std::linear_congruential_engine<std::uint_fast32_t, 16807, 0, 2147483647> Lewis, Goodman, Miller によって 1969 年に発見され、 Park と Miller によって 1988 年に「最低基準」として選定されたもの |
minstd_rand | std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647> Park, Miller, Stockmeyer によって 1993 年に推奨された新たな「最低基準」 |
mt19937 | std::mersenne_twister_engine<std::uint_fast32_t, 32, 624, 397, 31, |
mt19937_64 | std::mersenne_twister_engine<std::uint_fast64_t, 64, 312, 156, 31, |
ranlux24_base | std::subtract_with_carry_engine<std::uint_fast32_t, 24, 10, 24> |
ranlux48_base | std::subtract_with_carry_engine<std::uint_fast64_t, 48, 5, 12> |
ranlux24 | std::discard_block_engine<std::ranlux24_base, 223, 23> Martin Lüscher と Fred James による 24 ビットの RANLUX ジェネレータ (1994年) |
ranlux48 | std::discard_block_engine<std::ranlux48_base, 389, 11> Martin Lüscher と Fred James による 48 ビットの RANLUX ジェネレータ (1994年) |
knuth_b | std::shuffle_order_engine<std::minstd_rand0, 256> |
default_random_engine | 処理系定義 |
[編集]非決定的な乱数
std::random_device は非決定的な一様乱数を生成します。 処理系に非決定的な乱数生成のサポートがない場合は擬似乱数エンジンを使用して実装されるかもしれません。
ハードウェアエントロピーソースを使用する非決定的な乱数生成器 (クラス) |
[編集]乱数分布
乱数分布は乱数エンジンの出力を後処理し、定義された統計的確率密度関数に従って分布させます。
乱数分布は 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(){// Seed with a real random value, if availablestd::random_device r; // Choose a random mean between 1 and 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'; // Generate a normal distribution around that meanstd::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言語リファレンス |