新标准之前,使用C库rand生成随机数,生成均匀分布的伪随机整数,每个随机数的范围在0和一个系统相关的最大值(至少为 32767 ) 之间。但是无法自定义是否均匀分布、随机范围、随机数类型。
新标准通过以下一组类来满足有关随机数的需求:

  • 随机数引擎类
    • 是一个函数对象,不接受参数,返回一个随机unsigned。
  • 随机数分布类
    • 使用引擎返回服从特定概率分布的随机数。
    • 都是模板,除了bernoulli_distribution。

随机数发生器:引擎类 + 分布类。

  1. #include<random> // 在头文件random中。
  2. uniform_int_distribution<unsigned> u(0,9); // 分布类型:均匀分布,0~9的unsigned
  3. default_random_engine e; // 引擎类型:编译器选择的默认引擎。
  4. cout << u(e) << " "; // u(e):随机数发生器,返回一个unsigned int

随机数引擎

一个函数对象,不接受参数,返回一个随机unsigned数。
标准库有多个引擎类型,default_random_engine是一个类型别名,表示由编译器指定的默认引擎类型。

  1. default_random_engine e; // 使用编译器默认的随机数引擎,生成随机无符号数
  2. for(size_t i = 0; i < 10; ++i)
  3. cout << e() << " ";
  4. //16807 282475249 1622650073 984943658 1144108930 470211272
  5. uniform_int_distribution<unsigned> u(0,9); // 分布类型:均匀分布,0~9的unsigned int
  6. default_random_engine e; // 引擎类型:编译器默认。
  7. for (size_t i= 0; i < 10; ++i)
  8. // 将u作为随机数源,每个调用返回在指定范围内并服从均匀分布的值
  9. cout << u(e) << " " // 0 1 7 4 5 2 0 6 6 9

支持的操作

  1. Engine e; // 默认构造函数,使用该引擎类型默认的种子
  2. Engine e(s); // 使用整型值s作为种子
  3. e.seed(s); // 使用种子s重置引擎的状态
  4. e.min(); // 此引擎可生成的最小值
  5. e.max(); // 此引擎可生成的最大值
  6. Engine::result_type // 此引擎生成的unsigned整型类型
  7. e.discard(u) // 将引擎推进u步,u类型为unsigned long long

序列相同问题,一个给定的随机数发生器一直会生成相同的随机数序列。
如果定义了局部的发生器,应该将其定义为static,来保存状态,每次生成的都是新的数,避免重复生成序列。

  1. void func(){
  2. uniform_int_distribution<unsigned> u(0,9);
  3. default_random_engine e;
  4. for (size_t i= 0; i < 10; ++i)
  5. cout << u(e) << " ";
  6. //每次func()的结果都是:0 1 7 4 5 2 0 6 6 9
  7. }
  8. void func(){
  9. // 定义为static,保存状态
  10. static uniform_int_distribution<unsigned> u(0,9);
  11. static default_random_engine e;
  12. for (size_t i= 0; i < 10; ++i)
  13. cout << u(e) << " "; //每次func()的结果都不一样。
  14. }

种子seed

就是一个数值,引擎可以利用它从序列中一个新位置重新开始生成随机数。
种子是否相同,决定随机序列是否相同。
所以选择种子非常讲究,下面例子中有一个稍微随机一点的种子。

  1. default_random_engine e1; // 使用默认种子
  2. default_random_engine e2(2147483646); // 使用给定的种子值
  3. default_random_engine e3; // 使用默认种子值
  4. e3.seed(32767); // 调用seed设置一个新种子值
  5. default_random_engine e4(32767); // 将种子值设置为32767
  6. // e3和e4有相同的种子seed,将生成相同的序列。
  7. // time在头文件ctime中
  8. // time(data),返回当前距某个特定时刻过了多少秒,输入到data中。
  9. // time(0),直接返回秒数
  10. //
  11. // 随机改变的种子值
  12. // 但还是不够随机,函数运行在1s之内,种子就相同。
  13. //
  14. default_random_engine el(time(0));

随机数分布类

分布类型都是模板,接受一个模板参数,表示生成的随机数的类型。
浮点值分布类型,默认是double型随机数。
整型分布类型,默认是int型随机数。

  1. uniform_real_distribution<> u(0, 1); // 默认生成double值
  2. // 空<>表示我们希望使用默认结果类型
  3. uniform_real_distribution<double> u(0,1); // 0到1(包含)的均匀分布,返回double类型
  4. uniform_int_distribution<unsigned> u(0,9); // 返回unsigned int类型。

支持的操作

  1. Dist d; // 默认构造函数;使d准备好被使用。
  2. // 其他构造函数依赖于Dist的类型
  3. // 分布类型的构造函数是explicit的
  4. d(e) // 用相同的e连续调用d的话,会根据d的分布式类型生成一个随机数序列;
  5. // e是一个随机数引擎对象
  6. d.min() // 返回d(e)能生成的最小值
  7. d.max() // 返回d(e)能生成最大值
  8. d.reset() // 重建d的状态,使得随后对d的使用不依赖于d已经生成的值

类型

除了伯努利分布,其他都是模板。

均匀分布

  1. // IntT:表示整型类型,不包括bool、char,short、int、long
  2. // RealT:表示浮点类型,float、double、long double
  3. //生成指定类型的,在给定包含范围内的值。
  4. uniform_int_distribution<IntT> u(m=0, n=max); // m最小值,n是IntT类型的最大值
  5. uniform_real_distribution<RealT> u(x=0.0, y=1.0); // m最小值,n最大值
  6. //空<>表示我们希望使用默认结果类型
  7. uniform_real_distribution<> u(0, 1); // 默认生成double值
  8. uniform_int_distribution<> u(0, 9); // 默认生成int

伯努利分布

  1. // IntT:表示整型类型,不包括bool、char,short、int、long
  2. // RealT:表示浮点类型,float、double、long double
  3. bernoulli_distribution b(p=0.5); // p概率返回true
  4. binomial_distribution<IntT> b(t=1, p=0.5); // t:采用大小,整型值。
  5. geometric_distribution<IntT> g(p=0.5); // 每次试验成功的概率p
  6. negative_binomial_distribution<IntT> nb(k=1, p=0.5); // k次试验成功的概率为p
  7. default_random_engine e;
  8. bernoulli_distribution b(.55); // 0.55的概率返回true
  9. b(e); //0.55的概率返回true

泊松分布

  1. // IntT:表示整型类型,不包括bool、char,short、int、long
  2. // RealT:表示浮点类型,float、double、long double
  3. poisson_distribution<IntT> p(x); // 均值为x的分布,x为double类型。
  4. //指数分布,参数lambda通过浮点值lam给出
  5. exponential_distribution<RealT> e(lam=1.0);
  6. gamma_distribution<RealT> g(a=1.0, b=1.0); // 形状参数a, 尺度参数b
  7. weibul.l._distribution<Real.T> w(a=1.0, b=1.0); // 形状参数为a, 尺度参数为b的分布
  8. extreme_value_distribution<Real.T> e(a=0.0, b=1.0);

正态分布

  1. // IntT:表示整型类型,不包括bool、char,short、int、long
  2. // RealT:表示浮点类型,float、double、long double
  3. normal_distribution<RealT>n(m=0.0, s=1.0); // 均值:m,标准差:S
  4. lognormal_distribution<RealT>ln(m=0.0, s=1.0); // 均值:m,标准差:S
  5. chi_squared_distribution<RealT>c(x=1.0); // 自由度为x
  6. cauchy_distribution<RealT>c(a=0.0, b=1.0); // 位置参数a和尺度参数b
  7. fisher_f_distribution<RealT>f(m=1, n=1); // 自由度为m和n
  8. student_t_distribution<RealT>s(n=1); // 自由度为n

抽样分布

  1. // IntT:表示整型类型,不包括bool、char,short、int、long
  2. // RealT:表示浮点类型,float、double、long double
  3. discrete_distribution<IntT> d(i, j); // i和j是一个权重序列的输入迭代器
  4. discrete_distribution<IntT> d{ il }; // il是一个权重的花括号列表,必须能转成double
  5. piecewise_constant_distribution<RealT> pc(b,e,w); // b、e和w是输入迭代器。
  6. piecewise_linear_distribution<RealT> pl(b,e,w); // b、e和w是输入迭代器。