c++进阶STL-随机数
文章目录
- 介绍
- 知识点
- 库中的Distribution 和 Engine
- 生成随机序列
- 其他类型分布
- 浮点数分布
- Normal Distribution
- Bernoulli distribution
介绍
在新的标准之前,C和C++产生随机数都依赖与简单的C库函数rand(),这个函数产生一个伪随机数均匀分布在[0-system dependent maximum value(at least 32767)]。
但是rand()函数存在问题:有的程序需要不同的随机数范围,有的程序需要浮点随机数,有的程序可能需要的不是均匀分布的随机数。所以在程序员处理、转换这些问题的时候往往可能引入不随机的特性。
为了解决这个为题,新的c++库引入随机数库,定义在
Engine | Distribution |
---|---|
生成无符号整型的随机序列 | 利用Engine,根据特定的分布,返回随机数 |
random-number generator:指的是distribution 的对象关联一个Engine
知识点
库中的Distribution 和 Engine
详见: c++ prime p883-p885
distribution | 说明 |
---|---|
均匀分布 | ** |
uniform_int_distribution<types> u(m,n) | 产生[m,n]均匀分布的整数 |
uniform_real_distribution<types> u(m,n) | 产生[m,n]默认[0-1]均匀分布的实数 |
伯努利分布 | ** |
bernoulli_distribution b( p ) | |
binomial_distribution<types>b(t, p) | |
geometric_distribution<types> g( p ) | |
negative_binomial_distribution<types> nb(k, p) | |
泊松分布 | * |
poisson_distribution<types> p(x) | |
exponential_distribution<types> e (lam) | |
gamma_distribution <types> g(a, b) | |
weibull_distribution<types> w (a, b) | |
正态分布 | * |
normal_distribution<types> n (m, s) | |
lognomal_distribution<types> ln (m, s) | |
chi_squared_distribution<types> c ( x ) | |
cauchy_distribution<types> c (a, b) | |
fisher_fdistribution<types> f (m, n) | |
student_tdistribution<types> s( n) | |
抽样分布 | * |
discrete_distribution<types> d( i, j ) | |
discrete__distribution<types> d { il } | |
piecewise_constant_distribution<types> pc(b, e, w) | |
piecewise_linear_distribution<types> pl(b, e, w) |
Engine | 说明 |
---|---|
default_random_engine | |
shuffle_order_engine | |
linear_congruential_engine | |
mersenne_twister_engine | |
subtract_with_carry_engine | |
discard_block_engine | |
independent_bits_engine |
生成随机序列
我们需要注意的是:一个给定的random-number generator每次生成的序列都是一样的(这种情况有时候便于调试),如下代码:
vector
bad_randVec()
{default_random_engine e;
uniform_int_distribution<unsigned int> u(0, 9);
vector<unsigned int> ret;
for(int i=0; i<10; i++)
ret.push_back(u(e));
return ret;
}
如果想每个调用这个函数每次生成的序列不一样,有两种方案:
(利用static):
vector
bad_randVec()
{static default_random_engine e;
static uniform_int_distribution<unsigned int> u(0, 9);
vector<unsigned int> ret;
for(int i=0; i<10; i++)
ret.push_back(u(e));
return ret;
}
利用seed
- 手动提供种子
defalut_random_engine e(32767); //第一种:初始化的时候
e.seed(32767) // 第二种: 初始化之后,调用成员函数
利用time()函数,头文件
defalut_random_engine e(time(0));
利用random_device,random_device提供()操作符,用来返回一个min()到max()之间的一个数字.可以理解真随机数
std::random_device rd;
defalut_random_engine e(rd(0));
其他类型分布
浮点数分布
以前通常是使用 rand()/RADN_MAX来产生[0 1]的实数均匀分布。但这是不准确的,因为int型相比于浮点数通常是精确度低,所以有的浮点数永远不会生成。
default_random_engine e;
uniform_real_distribution<double> u(0,1);
for(size_t i=0; i<10; i++)
cout << u(e) << " ";
注意:如果想使用默认的数据类型的分布(通常浮点数:double, 整数:int), 我们传递模板参数为空,如:uniform_real_distribution<> u(0,1)
Normal Distribution
default_random_engine e;
normal_distribution<> n(4, 1.5);
vector<unsigned> vals(9); //记录0-9的每个数字的个数
for(size_t i=0; i<200; i++)
{
unsigned v = lround(n(e));
if(v< vals.size())
++vals[v];
}
for(size_t j=0; j!= vals.size(); ++j)
cout << j << ": " << string(vals[j], '*') << endl;
Bernoulli distribution
这不是一个模板类,是一个普通类,返回总是bool value
举例:假如你和电脑玩游戏,总有一个人先开始,who is first,我们可以通过 uniform_int_distribution
string resp;
default_random_engine e;
bernoulli_distribution b; // 默认 返回 true : false = 0.5 : 0.5
//bernoulli_distribution b(0.55); // 返回 true:false = 0.55:0.45
do
{
bool first = b(e);
cout << (first ? "computer first" : "you first") << endl;
cout << (play_game(first) ? "sorry, you lost" : "congratulations, you won" ) << endl;
cout << "pay again? enter yes or no" << endl;
}while(cin >> resp && resp[0] == 'y')
值得注意的是,我们 declare engine outside of loops,所以每次产生结果不一样,如果在loop内声明的话,每次的结果都是一样的
还没有评论,来说两句吧...