C++ 进阶(23):随机数库——random 深入、分布引擎、均匀分布、正态分布
更新时间:2026-09-01。本文是
languages/cpp/intermediate/进阶第 23 篇,接 format 格式化库。C++11 引入了<random>,终于有了像样的随机数库。引擎(engine)产生随机位,分布(distribution)把随机位映射到特定分布,职责分离。
本文要回答的问题
- 随机数引擎和分布器是什么关系?为什么分开?
- 常用的引擎有哪些?
mt19937、minstd_rand、random_device分别适合什么场景? - 怎么生成均匀分布、正态分布、离散分布的随机数?
- 种子怎么管理?为什么不要用
rand()和srand()?
一、引擎和分布器
cpp
#include <random>
// 引擎:产生随机位
// 分布器:把随机位映射到特定分布
// 基本用法
std::random_device rd; // 真随机数种子(硬件)
std::mt19937 gen(rd()); // Mersenne Twister 引擎
std::uniform_int_distribution<> dist(1, 6); // 产生 1-6 的整数
int dice = dist(gen); // 掷骰子二、常用引擎
cpp
// 1. std::mt19937 — Mersenne Twister,最常用
std::mt19937 gen(42); // 种子 42
// 优点:周期长(2^19937-1),均匀性好
// 缺点:状态大(2.5KB),初始化慢
// 2. std::minstd_rand — 线性同余,快速,状态小
std::minstd_rand gen2(42);
// 优点:状态小(4 字节),初始化快
// 缺点:周期短(2^31-2),质量不如 mt19937
// 3. std::random_device — 真随机数(硬件熵源)
std::random_device rd;
int seed = rd(); // 不可预测
// 注意:某些实现(MinGW)不是真随机,是伪随机!三、常用分布器
cpp
std::mt19937 gen(std::random_device{}());
// 均匀整数分布
std::uniform_int_distribution<> dice(1, 6); // [1, 6]
auto v = dice(gen);
// 均匀浮点分布
std::uniform_real_distribution<> prob(0.0, 1.0); // [0, 1)
auto p = prob(gen);
// 正态分布(高斯分布)
std::normal_distribution<> height(170.0, 10.0); // 均值 170,标准差 10
auto h = height(gen);
// 二项分布
std::binomial_distribution<> coin(1, 0.5); // 抛硬币
auto heads = coin(gen);
// 离散分布(指定权重)
std::discrete_distribution<> weather({0.3, 0.5, 0.2});
// 0: 晴天(30%), 1: 多云(50%), 2: 雨天(20%)
auto w = weather(gen);
// 泊松分布
std::poisson_distribution<> arrival(4.0); // 平均每小时 4 个事件
auto n = arrival(gen);四、种子管理
cpp
// 好的种子管理
std::random_device rd;
std::mt19937 gen(rd());
// 种子序列(seed_seq):多个种子混合
std::seed_seq seq{rd(), rd(), rd()};
std::mt19937 gen2(seq);
// 保存状态,方便重现
std::mt19937 gen3(rd());
auto state = gen3; // 保存当前状态
// 下次用 state 恢复,可以重现相同的随机序列五、不要再用 rand()
cpp
// ❌ 旧式:rand() 质量差,范围小,不是线程安全的
int v = rand() % 100; // 有偏,低几位随机性差
// ✅ 新式:C++11 random
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dist(0, 99);
int v = dist(gen);六、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
| 每次运行都产生相同序列 | 种子固定 | 用 random_device{}() 做种子 |
用 rand() % N | 低几位随机性差,分布有偏 | 用 uniform_int_distribution |
| random_device 在某些实现不是真随机 | 每次结果可预测 | 检查实现,或混合多个熵源 |
| 每次循环都创建引擎 | 产生相同序列 | 引擎创建一次,复用 |
相关与延伸
下一篇:可选值、变体、任意类型——optional、variant、any 实战;C 的随机数,见 C random。
一句话总结
C++ random 库:分离引擎(产生随机位)和分布器(映射到分布);最常用 mt19937 引擎 + uniform_int_distribution;random_device 提供真随机种子;uniform_real_distribution 浮点均匀,normal_distribution 正态分布,discrete_distribution 指定权重;不要用 rand(),用 random_device 做种子,mt19937 做引擎;引擎创建一次,复用。