偽隨機數生成
隨機數庫提供了生成隨機數和偽隨機數的類。這些類包括
- 均勻隨機位元生成器 (URBG),其中包括隨機數引擎(生成均勻分佈的整數序列的偽隨機數生成器)和真隨機數生成器(如果可用)。
- 隨機數分佈(例如 均勻分佈、正態分佈 或 泊松分佈),它們將 URBG 的輸出轉換為各種統計分佈。
URBG 和分佈旨在配合使用以生成隨機值。所有隨機數引擎都可以進行特定播種、序列化和反序列化,以便與可重複的模擬器一起使用。
目錄 |
[編輯] 均勻隨機位元生成器
一個*均勻隨機位元生成器*是一個返回無符號整數值的函式物件,其中可能結果範圍內的每個值都具有(理想情況下)相等的返回機率。
所有均勻隨機位元生成器都滿足 UniformRandomBitGenerator 要求。C++20 還定義了一個 uniform_random_bit_generator
概念。
定義於標頭檔案
<random> | |
(C++20) |
指定型別是否符合統一隨機位生成器 (概念) |
[編輯] 隨機數引擎
*隨機數引擎*(通常簡稱為*引擎*)是一個均勻隨機位元生成器,它使用種子資料作為熵源生成偽隨機數。
在任何給定時間,型別為 E
的引擎 e 具有狀態 ei
,其中 i 為某個非負整數。構造時,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 來生成。
標準庫以類模板的形式提供了三類不同偽隨機數生成演算法的實現,因此可以定製這些演算法。選擇使用哪個引擎涉及到一些權衡
- 線性同餘引擎 速度適中,狀態儲存要求非常小。
- Mersenne twister 引擎 速度較慢,狀態儲存要求較高,但在正確的引數下,它具有最長的非重複序列和最理想的頻譜特性(對於給定理想的定義)。
- 帶借位減法引擎 即使在沒有高階算術指令集的處理器上也非常快,但代價是更大的狀態儲存和有時不太理想的頻譜特性。
|
(C++26 起) |
這些隨機數引擎都不是 密碼安全的。與任何安全操作一樣,為此目的應使用加密庫(例如 OpenSSL RAND_bytes
)。
從這些模板例項化的所有型別都滿足 RandomNumberEngine 要求。
定義於標頭檔案
<random> | |
(C++11) |
實現 線性同餘 演算法 (類模板) |
(C++11) |
實現 Mersenne twister 演算法 (類模板) |
(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>1969 年由 Lewis, Goodman 和 Miller 發現,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) |
根據 Fisher's F-分佈 生成實數值 (類模板) |
(C++11) |
根據 Student's 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 文件 用於 偽隨機數生成
|