在C++中有两种获得随机数的方法,一个是位于<cstdlib>中的rand函数,一个是C++11中引入的<random>。
rand函数
rand 函数返回一个int类型的整数,其值位于0至RAND_MAX之间(包含两端)。其中,RAND_MAX依赖于库的实现,保证至少为32767。经过测试,这个值在VS 2015以及MinGW gcc 7中均为32767,而在Ubuntu 64bit gcc 中为2147483647。一般来说,可以使用以下方式获取随机数:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
// 获取10个随机数
for(int i = 0; i < 10; i++)
cout << rand() << endl;
}
实验发现,每次执行上述代码都产生相同的序列。这是因为这种获取随机数的方式产生的是伪随机数,每次执行代码前,随机数的种子都相同,因此获得的随机数序列也相同,为了获得不同的随机数序列,可以为随机数设置不同的种子。
由于相同的随机数种子产生相同的随机数序列,因此通常采用将当前的系统时间作为随机数种子,这样每次运行时随机数种子一般都不相同。
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
// 设置随机数种子
srand((unsigned)time(nullptr));
// 产生10个随机数
for(int i = 0; i < 10; i++)
cout << rand() << endl;
}
<random>
由于种种原因,采用rand函数产生的随机数在随机性上有一定的缺陷,对于严格的需求,不建议采用rand来获取随机数,而是使用C++11中引入的random。
一个简单的获取随机数的方法是使用random_device类。这是一个生成均匀分布的随机数的生成器,假如有可用的可以产生真随机数的硬件设备,random_device将产生真随机数序列,如果没有用于产生真随机数的设备,则采用伪随机数的方式实现。random_device生成unsigned类型的随机数,一般情况下介于0与4294967295之间。
#include <iostream>
#include <random>
using namespace std;
int main() {
random_device rd;
// 产生10个随机数
for(int i = 0; i < 10; i++) {
cout << rd() << endl;
}
}
一般来说,每次执行上述代码应该产生不同的随机数序列,但在测试MinGW时,每次产生的序列都相同,这应该是它的一个BUG。
虽然random_device可以获取真随机数,但由于其受产生随机数的硬件限制,所以一般用于为伪随机数引擎生成种子。C++标准库实现了linear_congruential_engine(线性同余算法),mersenne_twister_engine(梅森缠绕器算法)以及subtract_with_carry_engine(带进位减算法)等随机数引擎以及discard_block_engine,independent_bits_engine,shuffle_order_engine等适配器,以及基于这些引擎和适配器而定义的随机数生成器,例如:mt19937,mt19937_64,knuth_b等。可以采用以下方法使用随机数生成器。
#include <iostream>
#include <random>
using namespace std;
int main() {
random_device rd;
mt19937 mt(rd());
// 产生10个随机数
for(int i = 0; i < 10; i++) {
cout << mt() << endl;
}
}
除了随机数引擎外,C++还提供了获取服从不同分布的随机数的方法,例如均匀分布、伯努利分布、泊松分布、正态分布等。此处以均匀分布为例展示使用方法。
#include <iostream>
#include <random>
using namespace std;
int main() {
random_device rd;
mt19937 mt(rd());
// 产生位于[1, 100]间的随机数
uniform_int_distribution<int> randint(1, 100);
for(int i = 0; i < 5; i++)
cout << randint(mt) << ' ';
cout << endl;
// 产生位于[0.2, 0.8)间的随机数,注意区间
uniform_real_distribution<double> randdouble(0.2, 0.8);
for(int i = 0; i < 5; i++)
cout << randdouble(mt) << ' ';
cout << endl;
}
C++中提供的获取随机数的方法可以满足大部分需求,对于生成一般的随机数,建议使用随机数引擎(如mt19937等),生成某个区间的随机数则根据需要选择不同的分布(如uniform_int_distribution等),出于实用性考虑不建议使用rand函数产生随机数。
本文由kedixa发表于个人博客,
转载请注明作者及出处。
本文链接:https://blog.kedixa.top/2018/cpp-random-number/
学长的博客不错呀,大整数类学习了 ;D
我的博客,clew.cc和学长一比简直相形见拙