在C++中生成随机数的方法主要包括
std::rand
方法以及
random
库方法(C++11)。
std::rand 方法
std::rand
方法定义在cstdlib
(stdlib.h
)中,其作用是产生一个0
到RAND_MAX
之间的整数。其中RAND_MAX
是cstdlib
中定义的一个宏,产生的整数是均匀分布的。
在生成随机数之前可以用std::srand
来设置随机数种子,如果不设置的话随机数种子会默认设为1,其结果是每次生成的随机数序列都是一样的。
程序示例
例如,产生一个范围为1-6均匀分布的随机数可以用1 + std::rand()/((RAND_MAX + 1u)/6)
,完整代码如下:
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <vector>
int main()
{
std::srand(std::time(nullptr)); /* 用当前时间产生一个随机数种子 */
int random_variable = std::rand();
std::cout << "随机数的范围是 [0, " << RAND_MAX <<"]\n";
std::vector<unsigned int> vui = {1,2,3,4,5,6}; /* 存储各数字出现的次数 */
int x;
/* 生成20000个数 */
for (int n=0; n != 20000; ++n) {
x = 1 + std::rand()/((RAND_MAX + 1u)/6); /* 生成1-6的数字 */
vui[x-1]++;
}
for (int i=0; i<vui.size(); i++){
std::cout << "数字: " << i+1 << ", 次数 = " << vui[i] << std::endl;
}
return 0;
}
random库方法
在C++11中可以通过random
库来生成各种分布的随机数。
用random
库生成指定分布的随机数序列的步骤如下:
随机数种子
随机数种子可以直接指定,用当前时间生成或者干脆用随机数生成。
随机数生成器
random
库里提供了以下几个随机数生成器可供选择:
- minstd_rand0
- minstd_rand
- mt19937
- mt19937_64
- ranlux24_base
- ranlux48_base
- ranlux24
- ranlux48
- knuth_b
- default_random_engine
其中mt19937貌似性能比较好。例如,可以用不同的随机数种子来创建不同随机数生成器:
/* 用指定数字创建默认随机数生成器 */
std::default_random_engine e1(250+1);
/* 用当前时间创建mt19937随机数生成器 */
std::mt19937 e2(std::time(nullptr));
/* 用随机数创建knuth_b生成器 */
std::random_device r;
std::knuth_b e3(r());
随机数分布
random
库中提供以下五种分布:
- 均匀分布(Uniform distributions)
- 伯努利分布(Bernoulli distributions)
- 泊松分布(Poisson distributions)
- 正态分布(Normal distributions)
- 抽样分布(Sampling distributions)
其中每个分布都对应多种类型,例如均匀分布就含有uniform_int_distribution
和uniform_real_distribution
两种情况,分别返回整数和实数,具体内容可以参见这里。
可以通过以下代码创建不同随机数分布:
/* 创建1-6范围内的平均分布(整数) */
std::uniform_int_distribution<int> uniform_dist_int(1, 6);
/* 创建2-4范围内的平均分布(实数) */
std::uniform_real_distribution<float> uniform_dist_int(2, 4);
/* 创建均值为5,标准差为3的正态分布 */
std::normal_distribution<> normal_dist(5,3);
生成随机数
通过将随机数生成器传给随机数分布函数来生成随机数:
/* 产生一个均匀分布的整数 */
int rand1 = uniform_dist_int(e1);
/* 产生一个均匀分布的实数 */
float rand2 = uniform_dist_int(e2);
/* 产生一个正态分布的实数 */
float rand3 = normal_dist(e3);
程序示例
以下是用随机数作为种子,采用mt19937生成器生成0-10之间平均分布的实数的示例程序:
#include <iostream>
#include <vector>
#include <random>
int main(){
std::vector<int> vec = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float number;
std::random_device r; /* 1. 采用随机数作为种子 */
std::mt19937_64 e1(r()); /* 2. 设置mt19937作为随机数生成器 */
std::uniform_real_distribution<float> uniform_dist_int(0, 10); /* 3. 选择均匀实数分布 */
for (int i=0; i<1000; i++){
number = uniform_dist_int(e1); /* 4. 生成随机数 */
//std::cout << number << " ";
vec[(int)number]++;
}
std::cout << std::endl;
for (int i=0; i<vec.size(); i++){
std::cout << i << "-" << i+1 << ": " << vec[i] << std::endl;
}
return 0;
}