随机数生成算法有很多,C++11之前的C/C++只用了一种。C++11则提供下面三种可供选择:
linear_congruential_engine线性同余法
mersenne_twister_engine梅森旋转法
substract_with_carry_engine滞后Fibonacci
分布
描述
uniform_int_distribution
该分布接受一组上下限值作为构造函数的参数。之后得到的随机值就都是在这个范围中。我们可能得到的每个值的可能性是相同的,直方图将会是一个平坦的图像。这个分布就像是掷骰子,因为掷到骰子的每一个面的概率都是相等的。
normal_distribution
正态分布或高斯分布,自然界中几乎无处不在。其STL版本能接受一个平均值和一个标准差作为构造函数的参数,其直方图的形状像是屋顶一样。其分布于人类个体高度或动物的IQ值,或学生的成绩,都符合这个分布。
bernoulli_distribution
当我们想要一个掷硬币的结果时,使用伯努利分布就非常完美。其只会产生0和1,并且其构造函数的参数是产生1的概率。
discrete_distribution
当我们有一些限制的时候,我们就可以使用离散分布,需要我们为每个间隔的概率进行定义,从而得到离散集合的值。其构造函数会接受一个权重值类别,并且通过权重值的可能性产生相应的随机数。当我们想要对血型进行随机建模时,每种血型的概率是不一样,这样这种引擎就能很完美地契合这种需求。
#include <random> std::default_random_engine random; for (int i = 0 ; i < 20 ; ++i) int i = random ();
for (int i = 0 ; i < pwnd->m_sensorCount; ++i){ std::random_device rd; std::mt19937 gen{ rd () }; std::uniform_real_distribution<double > dis (-100.0 , 100.0 ) ; vDataBuf.push_back (dis (gen)); }
#include <iostream> #include <random> #include <time.h> using std::cout;using std::endl;using std::cin; int main () { std::uniform_real_distribution<double > dis2 (0.0 , 1.0 ) ; for (int i = 0 ; i < 10 ; ++i) { unsigned seed1 = std::chrono::system_clock::now ().time_since_epoch ().count (); std::default_random_engine random (seed1) ; std::uniform_int_distribution<int > dis1 (0 , 100 ) ; cout<<dis1 (random)<<' ' ; } cout<<endl; for (int i = 0 ; i < 10 ; ++i) cout<<dis2 (random)<<' ' ; cout<<endl; return 0 ; }
在uniform_int_distribution的构造函数中,参数说明了随机数的范围。uniform_int_distribution的随机数的范围不是半开范围[ ),而是[ ],对于uniform_real_distribution却是半开范围[ )。也是就是说上面的例子中,能产生100,但不会产生1.0。不得不说,这颠覆了之前的认识。对于default_random_engine来说,其产生的随机数范围是在[min(), max()]之间,其中min()和max()为它的两个成员函数。同样,也是非半开范围。对于浮点数,如果真的是想产生[0.0, 1.0]范围的数,可以使用
#include <cmath> #include <cfloat> std::uniform_real_distribution<double > dis2 (0 , std::nextafter(1 ,DBL_MAX)) ;
指定概率 discrete_distribution 参数是从 0-5 的数值出现的概率。 然后根据想要的数值范围 * 一个随机系数,得到范围值
std::random_device rd; std::mt19937 gen (rd()) ;std::discrete_distribution<> d ({ 1 , 5 , 14 , 30 ,30 ,20 }); std::map<int , int > m; int m1, m2;for (int n = 0 ; n < 10000 ; ++n) { m1 = d (gen); ++m[m1]; } for (auto p : m) { string str = to_string (p.first) + " generated " + to_string (p.second) + " times\r\n" ; _cprintf(str.c_str ()); }