名前空間
変種
操作

擬似乱数生成

From cppreference.com
< cpp‎ | numeric
 
 
 
 

乱数ライブラリは、乱数および擬似乱数を生成するクラスを提供します。これらのクラスには以下が含まれます。

  • 一様乱数ビット生成器 (Uniform random bit generators, URBGs)。これには、一様分布を持つ整数シーケンスを生成する擬似乱数生成器である乱数エンジンと、(利用可能な場合は)真の乱数生成器の両方が含まれます。
  • 乱数分布 (例: 一様分布正規分布ポアソン分布)。これはURBGの出力をさまざまな統計的分布に変換します。

URBGと分布は、乱数値を生成するために一緒に使用されるように設計されています。すべての乱数エンジンは、再現性のあるシミュレータで使用するために、特定のシード設定、シリアライズ、デシリアライズが可能です。

目次

[編集] 一様乱数ビット生成器

一様乱数ビット生成器とは、符号なし整数値を返す関数オブジェクトであり、結果として取りうる範囲の各値が(理想的には)等しい確率で返されます。

すべての一様乱数ビット生成器は、UniformRandomBitGenerator要件を満たします。C++20では、uniform_random_bit_generatorコンセプトも定義されています。

ヘッダー <random> で定義
型が一様乱数ビット生成器として適格であることを指定する
(コンセプト) [編集]

[編集] 乱数エンジン

乱数エンジン (一般的にエンジンと短縮される) は、エントロピー源としてシードデータを使用して擬似乱数を生成する一様乱数ビット生成器です。

任意の時点で、E型のエンジンeは、ある非負整数iに対する状態eiを持ちます。構築時、eは初期状態e0を持ち、これはエンジンパラメータと初期シード (またはシードシーケンス) によって決定されます。

任意のエンジン型Eに対して、以下のプロパティが常に定義されます

  • E::result_typeのサイズの倍数で表されるEの状態のサイズ (すなわち (sizeof ei) / sizeof(E::result_type))。
  • eの状態eiをその後続の状態ei+1に進める遷移アルゴリズムTA (すなわち TA(ei) == ei+1)。
  • eの状態をE::result_type型の値にマッピングする生成アルゴリズムGA。その結果が擬似乱数となります。

擬似乱数列は、TAGAを交互に呼び出すことで生成できます。

標準ライブラリは、3つの異なるクラスの擬似乱数生成アルゴリズムの実装をクラステンプレートとして提供しているため、アルゴリズムをカスタマイズできます。どのエンジンを使用するかの選択には、いくつかのトレードオフが伴います。

  • 線形合同法エンジンは、中程度の速度で、状態の保存に必要な領域が非常に小さいです。
  • メルセンヌ・ツイスターエンジンは、より低速で、状態の保存に必要な領域が大きくなりますが、適切なパラメータを使用すると、最も望ましいスペクトル特性を持つ最長の非反復シーケンスを生成します (望ましいの定義による)。
  • キャリー付き減算エンジンは、高度な算術命令セットを持たないプロセッサでも非常に高速ですが、状態の保存に必要な領域が大きく、スペクトル特性が劣ることがあります。
  • Philoxエンジンは、カウンタベースの乱数生成器です。状態が小さく、周期が長く(2^130以上)、大規模な並列乱数生成を必要とするモンテカルロシミュレーションでの使用を目的としています。容易にベクトル化・並列化でき、GPUに最適化されたライブラリで実装されています。
(C++26以降)

これらの乱数エンジンは、いずれも暗号論的に安全ではありません。安全な操作と同様に、その目的のためには暗号ライブラリを使用すべきです (例: OpenSSL RAND_bytes)。

これらのテンプレートからインスタンス化されたすべての型は、RandomNumberEngine要件を満たします。

ヘッダー <random> で定義
線形合同法アルゴリズムを実装
(クラステンプレート) [編集]
メルセンヌ・ツイスターアルゴリズムを実装
(クラステンプレート) [編集]
キャリー付き減算 (遅延フィボナッチ) アルゴリズムを実装
(クラステンプレート) [編集]
カウンタベースの並列化可能な生成器
(クラステンプレート) [編集]

[編集] 乱数エンジンアダプタ

乱数エンジンアダプタは、別の乱数エンジンをエントロピー源として使用して擬似乱数を生成します。これらは一般的に、基になるエンジンのスペクトル特性を変更するために使用されます。

ヘッダー <random> で定義
乱数エンジンの一部の出力を破棄する
(クラステンプレート) [編集]
乱数エンジンの出力を指定されたビット数のブロックにパックする
(クラステンプレート) [編集]
乱数エンジンの出力を異なる順序で提供する
(クラステンプレート) [編集]

[編集] 定義済み乱数生成器

いくつかの特定の一般的なアルゴリズムが定義済みです。

ヘッダー <random> で定義
定義
minstd_rand0 (C++11) std::linear_congruential_engine<std::uint_fast32_t,
                                16807, 0, 2147483647>

1969年にLewis、Goodman、Millerによって発見され、1988年にParkとMillerによって「最小標準」として採用された[編集]

minstd_rand (C++11)

std::linear_congruential_engine<std::uint_fast32_t,
                                48271, 0, 2147483647>
新しい「最小標準」。1993年にPark、Miller、Stockmeyerによって推奨された[編集]

mt19937 (C++11)

std::mersenne_twister_engine<std::uint_fast32_t,
                             32, 624, 397, 31,
                             0x9908b0df, 11,
                             0xffffffff, 7,
                             0x9d2c5680, 15,
                             0xefc60000, 18, 1812433253>
1998年の松本眞と西村拓士による32ビット版メルセンヌ・ツイスター[編集]

mt19937_64 (C++11)

std::mersenne_twister_engine<std::uint_fast64_t,
                             64, 312, 156, 31,
                             0xb5026f5aa96619e9, 29,
                             0x5555555555555555, 17,
                             0x71d67fffeda60000, 37,
                             0xfff7eee000000000, 43,
                             6364136223846793005>
2000年の松本眞と西村拓士による64ビット版メルセンヌ・ツイスター[編集]

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>

1994年のMartin LüscherとFred Jamesによる24ビットRANLUX生成器[編集]

ranlux48 (C++11) std::discard_block_engine<std::ranlux48_base, 389, 11>

1994年のMartin LüscherとFred Jamesによる48ビットRANLUX生成器[編集]

knuth_b (C++11) std::shuffle_order_engine<std::minstd_rand0, 256>[編集]
philox4x32 (C++26) std::philox_engine<std::uint_fast32_t, 32, 4, 10,
                   0xCD9E8D57, 0x9E3779B9,
                   0xD2511F53, 0xBB67AE85>[編集]
philox4x64 (C++26) std::philox_engine<std::uint_fast64_t, 64, 4, 10,
                   0xCA5A826395121157, 0x9E3779B97F4A7C15,
                   0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>[編集]
default_random_engine (C++11) 実装定義のRandomNumberEngine

[編集] 非決定論的乱数

std::random_deviceは非決定論的な一様乱数ビット生成器ですが、非決定論的な乱数生成がサポートされていない場合、実装はstd::random_deviceを擬似乱数エンジンを使用して実装することが許可されています。

ハードウェアエントロピー源を使用する非決定論的乱数生成器
(クラス) [編集]

[編集] 乱数分布

乱数分布は、URBGの出力を後処理し、結果の出力が定義された統計的確率密度関数に従うように分布させます。

乱数分布はRandomNumberDistributionを満たします。

ヘッダー <random> で定義
一様分布
範囲内で一様に分布する整数値を生成する
(クラステンプレート) [編集]
範囲内で一様に分布する実数値を生成する
(クラステンプレート) [編集]
ベルヌーイ分布
ベルヌーイ分布に従うbool値を生成する
(クラス) [編集]
二項分布に従う整数値を生成する
(クラステンプレート) [編集]
負の二項分布に従う整数値を生成する
(クラステンプレート) [編集]
幾何分布に従う整数値を生成する
(クラステンプレート) [編集]
ポアソン分布
ポアソン分布に従う整数値を生成する
(クラステンプレート) [編集]
指数分布に従う実数値を生成する
(クラステンプレート) [編集]
ガンマ分布に従う実数値を生成する
(クラステンプレート) [編集]
ワイブル分布に従う実数値を生成する
(クラステンプレート) [編集]
極値分布に従う実数値を生成する
(クラステンプレート) [編集]
正規分布
標準正規 (ガウス) 分布に従う実数値を生成する
(クラステンプレート) [編集]
対数正規分布に従う実数値を生成する
(クラステンプレート) [編集]
カイ二乗分布に従う実数値を生成する
(クラステンプレート) [編集]
コーシー分布に従う実数値を生成する
(クラステンプレート) [編集]
フィッシャーのF分布に従う実数値を生成する
(クラステンプレート) [編集]
スチューデントのt分布に従う実数値を生成する
(クラステンプレート) [編集]
標本分布
離散分布に従う整数値を生成する
(クラステンプレート) [編集]
一定の小区間で分布する実数値を生成する
(クラステンプレート) [編集]
定義された小区間で分布する実数値を生成する
(クラステンプレート) [編集]

[編集] ユーティリティ

ヘッダー <random> で定義
指定された精度の実数値を[01)の範囲に一様に分布させる
(関数テンプレート) [編集]
(C++11)
バイアスを除去する汎用スクランブルシードシーケンス生成器
(クラス) [編集]

[編集] 乱数アルゴリズム

ヘッダー <random> で定義
一様乱数ビット生成器からの乱数で範囲を埋める
(アルゴリズム関数オブジェクト)[編集]

[編集] C言語の乱数ライブラリ

上述のエンジンと分布に加えて、C言語の乱数ライブラリの関数と定数も利用可能ですが、推奨されません。

ヘッダ <cstdlib> で定義
擬似乱数を生成する
(関数) [編集]
擬似乱数生成器にシードを設定する
(関数) [編集]
std::randによって生成される最大値
(マクロ定数) [編集]

[編集]

#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <random>
#include <string>
 
int main()
{
    // Seed with a real random value, if available
    std::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 mean
    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"
              << std::fixed << std::setprecision(1);
    for (auto [x, y] : hist)
        std::cout << std::setw(2) << x << ' ' << std::string(y / 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言語ドキュメント擬似乱数生成
English 日本語 中文(简体) 中文(繁體)