命名空間
變體
動作

偽隨機數生成

出自 cppreference.com
 
 
 
 

隨機數庫提供了用於生成隨機數和偽隨機數的類別。這些類別包括:

  • 均勻隨機位元產生器 (URBG),包含隨機數引擎(生成具有均勻分佈整數序列的偽隨機數生成器)以及真隨機數生成器(若可用)。
  • 隨機數分佈(例如 均勻分佈常態分佈卜瓦松分佈),用於將 URBG 的輸出轉換為各種統計分佈。

URBG 與分佈被設計為協同工作以產生隨機值。所有的隨機數引擎都可以進行特定的播種(seeding)、序列化及反序列化,以便在可重現的模擬中使用。

目錄

[編輯] 均勻隨機位元產生器

均勻隨機位元產生器 是一個函數物件,返回無符號整數值,使得在可能結果範圍內的每個值(理想情況下)具有相等的返回機率。

所有均勻隨機位元產生器都滿足 UniformRandomBitGenerator 需求。C++20 還定義了一個 uniform_random_bit_generator 概念。

定義於標頭檔 <random>
指定一個類型符合均勻亂數位元生成器的資格
(概念) [edit]

[編輯] 隨機數引擎

隨機數引擎(通常簡稱為 引擎)是一種均勻隨機位元產生器,它使用種子資料作為熵源來生成偽隨機數。

在任何給定時間,類型為 E 的引擎 e 對於某個非負整數 i 具有一個狀態 ei。構造時,e 具有一個初始狀態 e0,該狀態由引擎參數和初始種子(或種子序列)決定。

對於任何引擎類型 E,始終定義以下屬性:

  • E 狀態的 大小(以 E::result_type 大小的倍數計)(即 (sizeof ei) / sizeof(E::result_type))。
  • 轉換演算法 TAe 的狀態 ei 通過它進階到後繼狀態 ei+1(即 TA(ei) == ei+1)。
  • 生成演算法 GAe 的狀態通過它映射為 E::result_type 類型的值,其結果即為偽隨機數。

偽隨機數序列可以通過交替呼叫 TAGA 來生成。

標準庫提供了三種不同類別的偽隨機數生成演算法的實作,以類別模板形式提供,以便演算法可以客製化。選擇使用哪種引擎涉及許多權衡:

  • 線性同餘引擎速度適中,且對狀態的儲存要求非常小。
  • 梅森旋轉演算法引擎速度較慢,且需要更多的狀態儲存空間,但在參數正確的情況下,它擁有最長的不重複序列,並具有最理想的譜特性(針對給定的「理想」定義)。
  • 帶進位減法引擎即使在沒有高階算術指令集的處理器上也非常快,代價是需要更大的狀態儲存空間,且有時譜特性較不理想。
  • Philox 引擎是一種基於計數器的隨機數生成器。它具有較小的狀態和較長的週期(不小於 2^130),旨在用於需要大規模平行隨機數生成的蒙地卡羅模擬中。它易於向量化與平行化,並在 GPU 優化庫中有實作。
(C++26 起)

這些隨機數引擎都不是加密安全的。對於任何安全操作,應使用加密庫(例如 OpenSSL RAND_bytes)。

所有由這些模板實例化的類型都滿足 RandomNumberEngine 需求。

定義於標頭檔 <random>
實作 線性同餘 演算法
(類別模板) [edit]
實作 梅森旋轉 演算法
(類別模板) [edit]
實作帶借位減法 (滯後費波那契) 演算法
(類別模板) [edit]
一種基於計數器的可平行化生成器
(類別模板) [edit]

[編輯] 隨機數引擎適配器

隨機數引擎適配器使用另一個隨機數引擎作為熵源來生成偽隨機數。它們通常用於改變底層引擎的譜特性。

定義於標頭檔 <random>
捨棄亂數引擎的部分輸出
(類別模板) [edit]
將亂數引擎的輸出打包成指定位元數的區塊
(類別模板) [edit]
以不同順序提供亂數引擎的輸出
(類別模板) [edit]

[編輯] 預定義隨機數生成器

預定義了幾種具體的常用演算法。

定義於標頭檔 <random>
類型 定義
minstd_rand0 (C++11) std::linear_congruential_engine<std::uint_fast32_t,
                                16807, 0, 2147483647>

由 Lewis、Goodman 和 Miller 於 1969 年發現,並於 1988 年由 Park 和 Miller 採用為「最小標準」[edit]

minstd_rand (C++11)

std::linear_congruential_engine<std::uint_fast32_t,
                                48271, 0, 2147483647>
由 Park、Miller 和 Stockmeyer 於 1993 年推薦的較新「最小標準」[edit]

mt19937 (C++11)

std::mersenne_twister_engine<std::uint_fast32_t,
                             32, 624, 397, 31,
                             0x9908b0df, 11,
                             0xffffffff, 7,
                             0x9d2c5680, 15,
                             0xefc60000, 18, 1812433253>
Matsumoto 和 Nishimura 於 1998 年發表的 32 位元梅森旋轉演算法[edit]

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>
Matsumoto 和 Nishimura 於 2000 年發表的 64 位元梅森旋轉演算法[edit]

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 於 1994 年提出的 24 位元 RANLUX 生成器[編輯]

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

由 Martin Lüscher 和 Fred James 於 1994 年提出的 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>[edit]
philox4x64 (C++26) std::philox_engine<std::uint_fast64_t, 64, 4, 10,
                   0xCA5A826395121157, 0x9E3779B97F4A7C15,
                   0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>[edit]
default_random_engine (C++11) 一種由實作定義的 RandomNumberEngine 類型

[編輯] 非決定性隨機數

std::random_device 是一種非決定性均勻隨機位元產生器,儘管如果沒有非決定性隨機數生成的支援,允許實作使用偽隨機數引擎來實作 std::random_device

使用硬體熵源的非確定性亂數生成器
(類別) [edit]

[編輯] 隨機數分佈

隨機數分佈對 URBG 的輸出進行後處理,使得所得結果根據定義的統計機率密度函數分佈。

隨機數分佈滿足 RandomNumberDistribution

定義於標頭檔 <random>
均勻分佈
生成在一個範圍內均勻分佈的整數值
(類別模板) [edit]
生成在一個範圍內均勻分佈的實數值
(類別模板) [edit]
白努利分佈
產生符合伯努利分佈bool (類別) [編輯]
生成依 二項分佈 的整數值
(類別模板) [編輯]
生成依 負二項分佈 的整數值
(類別模板) [編輯]
生成依 幾何分佈 的整數值
(類別模板) [編輯]
卜瓦松分佈
產生符合卜瓦松分佈的整數值 (類別模板) [編輯]
生成依 指數分佈 的實數值
(類別模板) [編輯]
生成依 伽瑪分佈 的實數值
(類別模板) [編輯]
生成依 韋伯分佈 的實數值
(類別模板) [編輯]
生成依 極值分佈 的實數值
(類別模板) [編輯]
常態分佈
生成依 標準常態 (高斯) 分佈 的實數值
(類別模板) [編輯]
生成依 對數常態分佈 的實數值
(類別模板) [編輯]
生成依 卡方分佈 的實數值
(類別模板) [編輯]
生成依 柯西分佈 的實數值
(類別模板) [編輯]
生成依 費雪 F-分佈 的實數值
(類別模板) [編輯]
生成依 學生 t-分佈 的實數值
(類別模板) [編輯]
抽樣分佈
產生符合離散分佈的整數值 (類別模板) [編輯]
生成在常數子區間上分佈的實數值
(類別模板) [編輯]
生成在定義的子區間上分佈的實數值
(類別模板) [編輯]

[編輯] 工具

定義於標頭檔 <random>
[01) 範圍內均勻分佈給定精度的實數值
(函式模板) [edit]
(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 Deutsch 日本語 中文(简体) 中文(繁體)