应使用 std::uniform_int_distribution 配合 std::random_device 和 std::mt19937 生成 [a, b] 闭区间内均匀随机整数,避免 rand() 因模偏差、周期短、范围控制不精确导致的问题。

用 std::uniform_int_distribution 生成指定范围的随机整数
现代 C++(C++11 起)推荐用 std::uniform_int_distribution 配合 std::random_device 和 std::mt19937,而不是老式 rand()。它能真正均匀分布,且范围控制精确、无偏移。
关键点:分布对象本身不生成随机数,它需要一个随机数引擎(如 std::mt19937)作为输入;构造时传入闭区间 [a, b] 即可,不需要手动加减 1。
std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distributiondist(10, 99); // 生成 [10, 99] 内的整数 int num = dist(gen); // 每次调用都得到一个新随机数
为什么不能用 rand() % N + a
这种写法看似简单,但存在严重缺陷:模运算会引入分布偏差,尤其当 RAND_MAX + 1 不能被 N 整除时,小余数对应的数字出现概率更高。例如 rand() % 100 在某些实现中会让 0–32 比 33–99 多出现一次。
-
rand()的周期短、质量差,且标准未规定其算法 -
RAND_MAX至少为 32767,但常见实现是 2147483647,仍不足以支撑高质量分布 - 无法直接控制上下界——
rand() % (b - a + 1) + a写法易错,且仍有偏差
生成 [a, b] 还是 [a, b)?注意闭区间语义
std::uniform_int_distribution 构造函数参数是**闭区间**:dist(a, b) 表示包含 a 和 b 的所有整数。这和 Python 的 random.randint(a, b) 一致,但不同于 std::uniform_real_distribution(它是左闭右开)。
立即学习“C++免费学习笔记(深入)”;
常见误用:
- 想生成 1–6(骰子),写了
dist(1, 5)→ 缺失 6 - 想生成 0–99,写了
dist(0, 99)✅ 正确,共 100 个数 - 混淆浮点分布写法,误以为要写
dist(1, 7)→ 实际会生成 1–7 共 7 个整数,不是 1–6
性能与复用建议:别每次新建分布对象
std::uniform_int_distribution 对象轻量,但**不应在循环内反复构造**;应定义为静态或成员变量,复用同一个实例。引擎(gen)也建议复用,避免重复初始化开销。
错误示范:
for (int i = 0; i < 1000; ++i) {
std::uniform_int_distribution dist(1, 6); // ❌ 每次都构造,低效且不必要
std::cout << dist(gen) << '\n';
} 正确写法:
std::uniform_int_distributiondist(1, 6); // ✅ 一次构造,多次调用 for (int i = 0; i < 1000; ++i) { std::cout << dist(gen) << '\n'; }
如果多线程环境使用,注意 gen 和 dist 都不是线程安全的——需为每个线程准备独立实例,或加锁。











