[C.C++] C++随机数生成

999 0
Honkers 2025-7-1 15:07:39 来自手机 | 显示全部楼层 |阅读模式

一、伪随机数生成

1. rand()

 rand()会返回一个随机数值,范围是在0至RAND_MAX间。RAND_MAX定义在stdlib.h头文件中,其值为2147483647。

2. srand()

 srand()可以用来设置rand()产生随机数时的随机数种子。通过设置不同的种子,可以获取不同的随机数序列。例如,可以利用srand(time(nullptr))的方式,根据系统时钟,产生不同的随机数种子。

3. 测试代码

  1. #include <iostream>
  2. #include <vector>
  3. #include <ctime>
  4. int main(int argc, char** argv){
  5. // 生成rand()的随机数种子
  6. srand(time(nullptr));
  7. for (int i = 0; i < 100; ++i){
  8. // 用rand()产生随机数
  9. std::cout << rand() << std::endl;
  10. std::cout << rand()/(RAND_MAX * 1.f) << std::endl;
  11. }
  12. return 0;
  13. }
复制代码

备注: 随机数生成的范围:
  1) [0, n),即rand() % n;
  2) [a, b),即rand() % (b - a) + a;
  3) [a, b],即rand() % (b - a + 1) + a;
  4) (a, b],即rand() % (b - a) + a + 1。
  5) a + rand() % n,[a, a + n);
  6) [0 , 1)之间的浮点数,rand()/(RAND_MAX * 1.f)

二、C++11随机数生成

1. 随机数生成算法

 相对于rand()和srand()生成伪随机数的方式来说,C++11的随机数生成器更加复杂,主要是因为在C++11中提供了比较多的选择方式
 C++11随机数生成方式有:
  1) linear_congruential_engine 线性同余随机数引擎
  2) mersenne_twister_engine 梅森旋转随机数引擎
  3) subtract_with_carry_engine 带进位随机数引擎
 上面的三种随机数生成算法均是模板类,需要我们自己进行实例化;模板类实例化需要的参数,均是算法中使用的参数,若是不懂其原理,建议不要使用这些模板类,因为我们不清楚用什么样的参数才能得到较好的随机序列。不过不用担心,在C++11标准中,已经帮我们预先定义了一些随机数类,它们都是用过上面的三个类模板实例化出来的。

类名称属性依赖类
linear_congruential_enginetemplates\
mersenne_twister_enginetemplates\
subtract_with_carry_enginetemplates\
discard_block_engineEngine adaptors\
independent_bits_engineEngine adaptors\
shuffle_order_engineEngine adaptors\
default_random_engineinstantiations待定
minstd_randinstantiationslinear_congruential_engine
minstd_rand0instantiationslinear_congruential_engine
mt19937instantiationsmersenne_twister_engine
mt19937_64instantiationsmersenne_twister_engine
ranlux24_baseinstantiationssubtract_with_carry_engine
ranlux48_baseinstantiationssubtract_with_carry_engine
ranlux24instantiationsranlux24_base、discard_block_engine
ranlux48instantiationsranlux48_base、discard_block_engine
knuth_binstantiationsshuffle_order_engine

 从上表中可以看出,在依赖类(第三列)中有一个”待定“,它的类是default_random_engine;它也是一个实例化的类。它的实现会和编译器有很大的关系,有的编译可能会用linear_congruential_engine,也可能会用mersenne_twister_engine。代码如下所示:

  1. #include <iostream>
  2. #include <random>
  3. int main(int argc, char**argv){
  4. std::default_random_engine engine;
  5. for (int i = 0; i < 10; ++i ){
  6. std::cout << engine() << " ";
  7. }
  8. std::cout << std::endl;
  9. return 0;
  10. }
复制代码

2. 随机数分布类型

  1. 均匀分布
     uniform_int_distribution 整数均匀分布
     uniform_real_distribution 浮点数均匀分布
  2. 伯努利类型分布
     bernoulli_distribution 伯努利分布
     binomial_distribution 二项分布
     geometric_distribution 几何分布
     negative_binomial_distribution 负二项分布
  3. Rate-based 分布
     poisson_distribution 泊松分布
     exponential_distribution 指数分布
     gamma_distribution 伽马分布
     weibull_distribution 威布尔分布
     extreme_value_distribution 极值分布
  4. 正态分布
     normal_distribution 正态分布
     lognormal_distribution 对数正态分布
     chi_squared_distribution 卡方分布
     cauchy_distribution 柯西分布
     fisher_f_distribution 费歇尔F分布
     student_t_distribution t分布
  5. 分段分布
     discrete_distribution 离散分布
     piecewise_constant_distribution 分段常数分布
     piecewise_linear_distribution 分段线性分布
  6. 其它
     seed_seq 种子序列
     generate_canonical 生成归一化
  1. #include <iostream>
  2. #include <random>
  3. #include <ctime>
  4. int main(int argc, char**argv){
  5. const int nrolls = 10000;
  6. const int nstars = 100;
  7. std::minstd_rand engine1(time(nullptr));
  8. int param = 10;
  9. std::poisson_distribution<int> distribution(param);
  10. int p[20] = {};
  11. for(int i = 0; i < nrolls; ++i){
  12. int tmp = distribution(engine1);
  13. if (20 > tmp) {
  14. ++p[tmp];
  15. }
  16. }
  17. std::cout << "poisson_distribution param: " << param << std::endl;
  18. for (int i = 0; i < 20; ++i){
  19. std::cout << i << ": " << std::string(p[i] * nstars/nrolls, '*') << std::endl;
  20. }
  21. return 0;
  22. }
  23. result:
  24. poisson_distribution param: 10
  25. 0:
  26. 1:
  27. 2:
  28. 3:
  29. 4: *
  30. 5: ***
  31. 6: ******
  32. 7: ********
  33. 8: ***********
  34. 9: ************
  35. 10: ************
  36. 11: ***********
  37. 12: **********
  38. 13: *******
  39. 14: *****
  40. 15: ***
  41. 16: **
  42. 17: *
  43. 18:
  44. 19:
复制代码

3. random_device

 random_device是标准库提供的一个非确定性随机数生成设备,是所有生成器中唯一一个不需要随机数种子的方式。在Linux中,是需要读取/dev/urandom设备。需要注意的是random_device在某些操作系统中是无法使用的,会在构造函数或者调用operator()函数时抛出异常,因此在进行代码移植时,需要格外注意。

  1. // random_device 说明
  2. // random_device::min() --- 范围最小值
  3. // random_device::max() --- 范围最大值
  4. // operator() --- 生成一个随机数
  5. // entropy() --- 计算operator()调用生成的随机数的熵,如果random库使用随机数引擎(即伪随机数算法)实现而不是真随机数生成器,那么该值为0
  6. #include <iostream>
  7. #include <random>
  8. #include <ctime>
  9. int main(int argc, char**argv){
  10. std::random_device rd;
  11. std::cout << "range: " << rd.min() << '\t' << rd.max() << std::endl;
  12. std::cout << "random1: " << rd() << std::endl;
  13. std::cout << "random2: " << rd() << std::endl;
  14. std::cout << "random3: " << rd() << std::endl;
  15. std::cout << "entropy: " << rd.entropy() << std::endl;
  16. return 0;
  17. }
  18. result:
  19. range: 0 4294967295
  20. random1: 2104889535
  21. random2: 1299396987
  22. random3: 1841354037
  23. entropy: 0
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2026 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行