命名空间
变体
操作

伪随机数生成

来自 cppreference.com
< cpp‎ | numeric
 
 
 
 

随机数库提供生成随机数和伪随机数的类。这些类包括

  • 均匀随机位生成器 (URBG),包括随机数引擎,它们是生成具有均匀分布的整数序列的伪随机数生成器,以及真正的随机数生成器(如果可用)。
  • 随机数分布(例如 均匀正态泊松分布)将 URBG 的输出转换为各种统计分布。

URBG 和分布旨在协同使用以生成随机值。所有随机数引擎都可以专门播种、序列化和反序列化,以用于可重复的模拟器。

内容

[编辑] 均匀随机位生成器

均匀随机位生成器是一个函数对象,它返回无符号整数值,使得可能结果范围内的每个值都具有(理想情况下)相等的返回概率。

所有均匀随机位生成器都满足 UniformRandomBitGenerator 要求。C++20 还定义了一个 uniform_random_bit_generator 概念。

定义在头文件 <random>
指定类型是否符合均匀随机位生成器的条件
(概念) [编辑]

[编辑] 随机数引擎

随机数引擎(通常缩写为引擎 )是一个均匀随机位生成器,它使用种子数据作为熵源来生成伪随机数。

在任何给定时间,类型为 E 的引擎 e 都有一个状态 e
i
,其中 i 是一个非负整数。构造时,e 具有初始状态 e
0
,它由引擎参数和初始种子(或种子序列)决定。

以下属性始终为任何引擎类型 E 定义

  • E 的状态大小,以 E::result_type 的大小倍数表示(即 (sizeof e
    i
    ) / sizeof(E::result_type)
    )。
  • 转换算法 TA,通过它将 e 的状态 e
    i
    推进到其后续状态 e
    i+1
    (即 TA(e
    i
    ) == e
    i+1
    )。
  • 生成算法 GA,通过它将 e 的状态映射到类型为 E::result_type 的值,结果是一个伪随机数。

可以通过交替调用 TAGA 来生成伪随机数序列。

标准库提供三种不同伪随机数生成算法类的实现作为类模板,以便可以自定义这些算法。选择使用哪个引擎涉及许多权衡

  • 线性同余引擎 速度中等,对状态的存储需求很小。
  • 梅森旋转器引擎 速度较慢,对状态的存储需求更大,但对于正确的参数,它具有最长的非重复序列,具有最理想的频谱特性(对于给定的理想定义)。
  • 带进位减法引擎 速度非常快,即使在没有高级算术指令集的处理器上也是如此,但代价是更大的状态存储,有时频谱特性也不理想。
  • 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>

由 Lewis、Goodman 和 Miller 在 1969 年发现,由 Park 和 Miller 在 1988 年采用为“最小标准”[编辑]

minstd_rand (C++11)

std::linear_congruential_engine<std::uint_fast32_t,
                                48271, 0, 2147483647>
Park、Miller 和 Stockmeyer 在 1993 年推荐的更新的“最小标准”[编辑]

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 位梅森旋转器[编辑]

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 位梅森旋转器[编辑]

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,
                   0xD2511F53, 0x9E3779B9,
                   0xCD9E8D57, 0xBB67AE85>[编辑]
philox4x64 (C++26) std::philox_engine<std::uint_fast64_t, 64, 4, 10,
                   0xD2E7470EE14C6C93, 0x9E3779B97F4A7C15,
                   0xCA5A826395121157, 0xBB67AE8584CAA73B>[编辑]
default_random_engine (C++11) 实现定义

[编辑] 非确定性随机数

std::random_device 是一个非确定性的均匀随机位生成器,尽管允许实现使用伪随机数引擎来实现 std::random_device,如果不存在对非确定性随机数生成的任何支持。

使用硬件熵源的非确定性随机数生成器
(类) [编辑]

[编辑] 随机数分布

随机数分布以特定方式对 URBG 的输出进行后处理,以使生成的输出符合定义的统计概率密度函数。

随机数分布满足 RandomNumberDistribution

定义在头文件 <random>
均匀分布
生成跨范围均匀分布的整数值
(类模板) [编辑]
生成跨范围均匀分布的实数值
(类模板) [编辑]
伯努利分布
伯努利分布 上生成 bool
(类) [编辑]
二项分布 上生成整数值
(类模板) [编辑]
负二项分布 上生成整数值
(类模板) [编辑]
几何分布 上生成整数值
(类模板) [编辑]
泊松分布
泊松分布 上生成整数值
(类模板) [编辑]
指数分布 上生成实数值
(类模板) [编辑]
伽马分布 上生成实数值
(类模板) [编辑]
威布尔分布 上生成实数值
(类模板) [编辑]
极值分布 上生成实数值
(类模板) [编辑]
正态分布
标准正态(高斯)分布 上生成实数值
(类模板) [编辑]
对数正态分布 上生成实数值
(类模板) [编辑]
卡方分布 上生成实数值
(类模板) [编辑]
柯西分布 上生成实数值
(类模板) [编辑]
费希尔 F 分布 上生成实数值
(类模板) [编辑]
学生 t 分布 上生成实数值
(类模板) [编辑]
抽样分布
在离散分布上生成随机整数
(类模板) [编辑]
在常数子区间上生成分布的实数值
(类模板) [编辑]
在定义的子区间上生成分布的实数值
(类模板) [编辑]

[编辑] 工具

定义在头文件 <random>
[01) 中以给定精度均匀分布实数值
(函数模板) [编辑]
(C++11)
通用消除偏差的混淆种子序列生成器
(类) [编辑]

[编辑] 随机数算法

定义在头文件 <random>
用来自均匀随机位生成器的随机数填充范围
(niebloid)[编辑]

[编辑] 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 文档 用于 伪随机数生成