CPP生成随机数
1.
传统方法:rand()
和
srand()
(C语言风格,不推荐在新项目中使用)
工作原理:
rand()
: 返回一个伪随机数,范围通常是0
到RAND_MAX
(一个常量,如 32767)。srand(seed)
: 设置随机数种子。如果使用相同的种子,rand()
会产生相同的序列。
缺点:
- 低质量:生成的随机数序列质量通常不高。
- 范围固定:范围固定为
[0, RAND_MAX]
,需要手动取模来调整范围,但这会引入偏差。 - 全局状态:使用全局状态,可能影响程序其他部分。
- 性能:在某些实现中性能不佳。
示例:
|
2.
现代方法:<random>
库 (C++11 推荐)
<random>
库将随机数生成分为两部分:
- 随机数引擎 (Engine):负责生成原始的随机数序列(通常是 unsigned integers)。
- 随机数分布 (Distribution):负责将引擎产生的数字映射到特定的范围或分布。
这种分离使得它非常灵活和强大。
2.1 随机数引擎
常用的引擎:
引擎类 | 说明 | 特点 |
---|---|---|
std::default_random_engine |
默认随机引擎 | 实现定义,通常是一个平衡的选择 |
std::mt19937 |
梅森旋转算法 | 最常用,高质量,周期极长
(2^19937-1 ) |
std::mt19937_64 |
64位梅森旋转算法 | 同上,但生成64位随机数 |
std::minstd_rand |
线性同余算法 | 较老,质量不如梅森旋转 |
std::random_device |
真随机数引擎 | 尝试使用硬件熵源(如RdRand),用于生成种子 |
2.2 随机数分布
常用的分布:
分布类 | 说明 | 范围/分布 |
---|---|---|
std::uniform_int_distribution<int> |
均匀整数分布 | [a, b] 之间的整数,每个数概率相等 |
std::uniform_real_distribution<double> |
均匀实数分布 | [a, b) 之间的浮点数 |
std::normal_distribution<double> |
正态分布(高斯分布) | 均值 μ ,标准差
σ |
std::bernoulli_distribution |
伯努利分布 | true 或
false ,像抛硬币 |
std::binomial_distribution<int> |
二项分布 | |
std::poisson_distribution<int> |
泊松分布 |
3. 现代方法的通用步骤和最佳实践
- 创建引擎:通常选择
std::mt19937
。 - 获取优质种子:使用
std::random_device
获取真随机数作为种子。 - 初始化引擎:用种子初始化引擎。
- 创建分布:选择你需要的分布(如
uniform_int_distribution
)。 - 生成随机数:将引擎传递给分布对象。
高质量示例:
|
4. 重要技巧和注意事项
避免在循环中创建引擎和分布:引擎和分布对象可以重复使用。在循环内部创建它们会严重影响性能且可能破坏随机性。
// 错误示范(性能极差)
for (int i = 0; i < 100; i++)
{
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(1, 6);
std::cout << dis(gen) << ' ';
}
// 正确示范(高效)
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(1, 6);
for (int i = 0; i < 100; i++)
{
std::cout << dis(gen) << ' ';
}生成无偏的整数范围:现代分布会自动处理范围而无偏差,无需再使用
%
。// 旧方法(有偏差):
int bad_range = std::rand() % 10; // 生成 0-9,但概率不完全相等
// 新方法(无偏差):
std::uniform_int_distribution<int> good_dist(0, 9);
int good_range = good_dist(gen); // 真正均匀的 0-9
总结
特性 | 传统 rand() |
现代 <random> |
---|---|---|
推荐度 | 不推荐(遗留代码) | 强烈推荐(新项目) |
灵活性 | 低 | 极高(引擎和分布可自由组合) |
随机性质量 | 通常较低 | 非常高(多种高质量算法) |
易用性 | 简单但不安全(取模有偏差) | 稍复杂但安全可靠(分布无偏差) |
性能 | 通常较快 | 可能稍慢,但质量换性能是值得的 |
对于任何新的 C++ 项目,都应该使用
<random>
库,并首选
std::mt19937
引擎和
std::uniform_int_distribution
/std::uniform_real_distribution
来满足基本的均匀分布需求。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 qyhome!