名稱空間
變體
操作

偽隨機數生成

來自 cppreference.com
< cpp‎ | 數值
 
 
 
 

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

  • 均勻隨機位元生成器 (URBG),其中包括隨機數引擎(生成均勻分佈的整數序列的偽隨機數生成器)和真隨機數生成器(如果可用)。
  • 隨機數分佈(例如 均勻分佈正態分佈泊松分佈),它們將 URBG 的輸出轉換為各種統計分佈。

URBG 和分佈旨在配合使用以生成隨機值。所有隨機數引擎都可以進行特定播種、序列化和反序列化,以便與可重複的模擬器一起使用。

目錄

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

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

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

定義於標頭檔案 <random>
指定型別是否符合統一隨機位生成器
(概念) [編輯]

[編輯] 隨機數引擎

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

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

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

  • E 狀態的大小,以 E::result_type 大小的倍數表示(即 (sizeof ei) / sizeof(E::result_type))。
  • 轉換演算法 TA,透過它將 e 的狀態 ei 推進到其後繼狀態 ei+1(即 TA(ei) == ei+1)。
  • 生成演算法 GA,透過它將 e 的狀態對映到 E::result_type 型別的值,結果是一個偽隨機數。

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

標準庫以類模板的形式提供了三類不同偽隨機數生成演算法的實現,因此可以定製這些演算法。選擇使用哪個引擎涉及到一些權衡

  • 線性同餘引擎 速度適中,狀態儲存要求非常小。
  • Mersenne twister 引擎 速度較慢,狀態儲存要求較高,但在正確的引數下,它具有最長的非重複序列和最理想的頻譜特性(對於給定理想的定義)。
  • 帶借位減法引擎 即使在沒有高階算術指令集的處理器上也非常快,但代價是更大的狀態儲存和有時不太理想的頻譜特性。
  • Philox 引擎 是一個 基於計數器的隨機數生成器。它具有小的狀態和長的週期(不小於 2^130),旨在用於需要大規模並行隨機數生成的蒙特卡羅模擬。它易於向量化和並行化,並在 GPU 最佳化庫中實現。
(C++26 起)

這些隨機數引擎都不是 密碼安全的。與任何安全操作一樣,為此目的應使用加密庫(例如 OpenSSL RAND_bytes)。

從這些模板例項化的所有型別都滿足 RandomNumberEngine 要求。

定義於標頭檔案 <random>
實現 線性同餘 演算法
(類模板) [編輯]
實現 Mersenne twister 演算法
(類模板) [編輯]
實現帶借位減法 (滯後斐波那契) 演算法
(類模板) [編輯]
基於計數器的可並行化生成器
(類模板) [編輯]

[編輯] 隨機數引擎介面卡

隨機數引擎介面卡使用另一個隨機數引擎作為熵源生成偽隨機數。它們通常用於改變底層引擎的頻譜特性。

定義於標頭檔案 <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 位 Mersenne Twister[編輯]

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 位 Mersenne Twister[編輯]

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

使用硬體熵源的非確定性隨機數生成器
(類) [編輯]

[編輯] 隨機數分佈

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

隨機數分佈滿足 RandomNumberDistribution

定義於標頭檔案 <random>
均勻分佈
產生在給定範圍內均勻分佈的整數值
(類模板) [編輯]
產生在給定範圍內均勻分佈的實數值
(類模板) [編輯]
伯努利分佈
根據 伯努利分佈 生成 bool
(類) [編輯]
根據 二項分佈 生成整數值
(類模板) [編輯]
根據 負二項分佈 生成整數值
(類模板) [編輯]
根據 幾何分佈 生成整數值
(類模板) [編輯]
泊松分佈
根據 泊松分佈 生成整數值
(類模板) [編輯]
根據 指數分佈 生成實數值
(類模板) [編輯]
根據 伽馬分佈 生成實數值
(類模板) [編輯]
根據 威布林分佈 生成實數值
(類模板) [編輯]
根據 極值分佈 生成實數值
(類模板) [編輯]
正態分佈
根據 標準正態(高斯)分佈 生成實數值
(類模板) [編輯]
根據 對數正態分佈 生成實數值
(類模板) [編輯]
根據 卡方分佈 生成實數值
(類模板) [編輯]
根據 柯西分佈 生成實數值
(類模板) [編輯]
根據 Fisher's F-分佈 生成實數值
(類模板) [編輯]
根據 Student's 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 文件 用於 偽隨機數生成