偽隨機數生成
隨機數庫提供了用於生成隨機數和偽隨機數的類別。這些類別包括:
- 均勻隨機位元產生器 (URBG),包含隨機數引擎(生成具有均勻分佈整數序列的偽隨機數生成器)以及真隨機數生成器(若可用)。
- 隨機數分佈(例如 均勻分佈、常態分佈 或 卜瓦松分佈),用於將 URBG 的輸出轉換為各種統計分佈。
URBG 與分佈被設計為協同工作以產生隨機值。所有的隨機數引擎都可以進行特定的播種(seeding)、序列化及反序列化,以便在可重現的模擬中使用。
目錄 |
[編輯] 均勻隨機位元產生器
均勻隨機位元產生器 是一個函數物件,返回無符號整數值,使得在可能結果範圍內的每個值(理想情況下)具有相等的返回機率。
所有均勻隨機位元產生器都滿足 UniformRandomBitGenerator 需求。C++20 還定義了一個 uniform_random_bit_generator 概念。
| 定義於標頭檔
<random> | |
| (C++20) |
指定一個類型符合均勻亂數位元生成器的資格 (概念) |
[編輯] 隨機數引擎
隨機數引擎(通常簡稱為 引擎)是一種均勻隨機位元產生器,它使用種子資料作為熵源來生成偽隨機數。
在任何給定時間,類型為 E 的引擎 e 對於某個非負整數 i 具有一個狀態 ei。構造時,e 具有一個初始狀態 e0,該狀態由引擎參數和初始種子(或種子序列)決定。
對於任何引擎類型 E,始終定義以下屬性:
E狀態的 大小(以E::result_type大小的倍數計)(即 (sizeof ei) / sizeof(E::result_type))。- 轉換演算法 TA,e 的狀態 e
i通過它進階到後繼狀態 ei+1(即 TA(ei) == ei+1)。 - 生成演算法 GA,e 的狀態通過它映射為
E::result_type類型的值,其結果即為偽隨機數。
偽隨機數序列可以通過交替呼叫 TA 和 GA 來生成。
標準庫提供了三種不同類別的偽隨機數生成演算法的實作,以類別模板形式提供,以便演算法可以客製化。選擇使用哪種引擎涉及許多權衡:
- 線性同餘引擎速度適中,且對狀態的儲存要求非常小。
- 梅森旋轉演算法引擎速度較慢,且需要更多的狀態儲存空間,但在參數正確的情況下,它擁有最長的不重複序列,並具有最理想的譜特性(針對給定的「理想」定義)。
- 帶進位減法引擎即使在沒有高階算術指令集的處理器上也非常快,代價是需要更大的狀態儲存空間,且有時譜特性較不理想。
|
(C++26 起) |
這些隨機數引擎都不是加密安全的。對於任何安全操作,應使用加密庫(例如 OpenSSL RAND_bytes)。
所有由這些模板實例化的類型都滿足 RandomNumberEngine 需求。
| 定義於標頭檔
<random> | |
| (C++11) |
實作 線性同餘 演算法 (類別模板) |
| (C++11) |
實作 梅森旋轉 演算法 (類別模板) |
| (C++11) |
實作帶借位減法 (滯後費波那契) 演算法 (類別模板) |
| (C++26) |
一種基於計數器的可平行化生成器 (類別模板) |
[編輯] 隨機數引擎適配器
隨機數引擎適配器使用另一個隨機數引擎作為熵源來生成偽隨機數。它們通常用於改變底層引擎的譜特性。
| 定義於標頭檔
<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 年發現,並於 1988 年由 Park 和 Miller 採用為「最小標準」 |
minstd_rand (C++11) |
std::linear_congruential_engine<std::uint_fast32_t, |
mt19937 (C++11) |
std::mersenne_twister_engine<std::uint_fast32_t, |
mt19937_64 (C++11) |
std::mersenne_twister_engine<std::uint_fast64_t, |
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> |
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。
| (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) |
通用消除偏差的攪亂種子序列生成器 (類別) |
[編輯] 隨機數演算法
| 定義於標頭檔
<random> | |
| (C++26) |
使用均勻隨機位元產生器生成的隨機數填充範圍 (演算法函式物件) |
[編輯] 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 文件 關於 偽隨機數生成
|