前言

一直知道所谓的"随机数"都是伪随机,事实上也是满足某种规则生成的。有些程序测试时通常需要一个随机数源,但在新标准出现之前,C++都是依赖简单的C库函数rand来生成随机数的。最近突然看到了C++11中的随机数发生器,简直如获珍宝,下面会谈一谈这两者的区别。

如何产生随机数

利用C库函数

头文件<stdlib.h>,但是注意在linux下stdlib.h包含srandom 和random ,但在VC下stdlib.h包含的是srand和rand

  1. x = rand()%11; /*产生1~10之间的随机整数*/
  2. y = rand()%51 - 25; /*产生-25 ~ 25之间的随机整数*/
  3. z = ((double)rand()/RAND_MAX)*(b-a) + a;/*产生区间[a,b]上的随机数*/

整理一下常见的产生随机数的通用表达公式为:

取得(0,x)的随机整数:rand()%x;

取得(a,b)的随机整数:rand()%(b-a);

取得[a,b)的随机整数:rand()%(b-a)+a;

取得[a,b]的随机整数:rand()%(b-a+1)+a;

取得(a,b]的随机整数:rand()%(b-a)+a+1;

取得0-1之间的浮点数:rand()/double(RAND_MAX)

比如说随便写个函数:

  1. #define random(x) (rand()%x)
  2. int main()
  3. {
  4. for (int i = 0; i < 10; ++i)
  5. cout << random(11) << " ";
  6. cout << endl;
  7. system("pause");
  8. }

你会发现两次运行这一段程序输出结果是一样的,说明rand这个函数所生成的随机数是一次性的,为了改进这一点,我们可以利用srand()函数,srand()是用来设置rand()产生随机数时的随机数种子。在调用rand()函数产生随机数前,必须先利用srand()设好随机数种子(seed), 如果未设随机数种子, rand()在调用时会自动设随机数种子为1。上面的两个例子就是因为没有设置随机数种子,每次随机数种子都自动设成相同值1 ,进而导致rand()所产生的随机数值都一样。

而我们一般会用时间来做为种子:

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<ctime>
  4. using namespace std;
  5. #define random(a,b) (((double)rand()/RAND_MAX)*(b-a)+a)
  6. void main() {
  7. srand((int)time(0));
  8. for (int i = 0; i < 100; i++) {
  9. cout << random(0, 10) << " ";
  10. }
  11. cout << endl;
  12. system("pause");
  13. }

C++随机数发生器

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

由于C库函数生成的为均匀分布的伪随机整数,但是如果我们需要非均匀分布的数的话,就会手工转换rand生成的随机数的范围、类型和分布,这样又引入了非随机性,不妥。所以我们可以用定义在头文件random中的随机数库通过一组写作的类来解决这些问题:随机数引擎和随机数分布类。引擎是用来生成随机unsigned整数序列的,分布是使用引擎返回服从特定概率分布的随机数。

首先利用引擎来产生随机数:

  1. #include<iostream>
  2. #include<random>
  3. #include<ctime>
  4. using namespace std;
  5. void main() {
  6. default_random_engine e; //生成随机无符号数
  7. for (size_t i = 0; i < 10; ++i)
  8. cout << e() << " ";
  9. cout << endl;
  10. cout << "seed Random:" << endl;
  11. e.seed(int(time(0)));
  12. for (size_t i = 0; i < 10; ++i)
  13. cout << e() << " ";
  14. system("pause");
  15. }
  16. //OUTPUT:
  17. 3499211612 581869302 3890346734 3586334585 545404204 4161255391 3922919429 949333985 2715962298 1323567403
  18. seed Random:
  19. 1209134335 963543660 450936573 838635935 555864927 2629301182 2752494759 772597830 1658101593 1483430385

但是一般来说,随机数引擎的输出是不能直接使用的,因为生成的随机数的值范围通常与我们需要的不符,所以还要加上分布类型,我们再给个完整的例子体会一下:

  1. #include<iostream>
  2. #include<random>
  3. #include<string>
  4. using namespace std;
  5. vector<unsigned> randVec()
  6. {
  7. static default_random_engine e;
  8. static uniform_int_distribution<unsigned> u(0, 9);
  9. vector<unsigned> ret;
  10. for (size_t i = 0; i < 20; ++i)
  11. ret.push_back(u(e));
  12. return ret;
  13. }
  14. vector<float> normalVec()
  15. {
  16. cout << "正态分布:" << endl;
  17. static default_random_engine e;
  18. static normal_distribution<float> n(4, 1.5);//均值4,方差1.5
  19. vector<float> res;
  20. vector<unsigned> vals(9);
  21. for (size_t i = 0; i != 20; ++i)
  22. {
  23. unsigned tmp = n(e);
  24. unsigned v = lround(tmp);
  25. if (v < vals.size())
  26. ++vals[v];
  27. res.push_back(tmp);
  28. }
  29. for (size_t j = 0; j != vals.size(); ++j)
  30. cout << j << ": " << string(vals[j], '*') << endl;
  31. return res;
  32. }
  33. template<typename T>
  34. void display(vector<T> a)
  35. {
  36. for (int i = 0; i < a.size(); ++i)
  37. {
  38. cout << a[i] << " ";
  39. }
  40. cout << endl;
  41. }
  42. void main() {
  43. vector<unsigned> res;
  44. res=randVec();
  45. cout << "均匀分布:" << endl;
  46. display(res);
  47. vector<float> res2;
  48. res2 = normalVec();
  49. display(res2);
  50. system("pause");
  51. }

结果如下:

更多的分布参数设置见下图:

C++11随机数发生器的更多相关文章

  1. C语言基础(11)-随机数发生器

    一. rand() rand是一个C语言库函数,功能是生成一个随机数.rand需要一个不同的种子,才能生成不同的随机数. 二. srand(int seed) rand需要一个不同的种子,才能生成不同 ...

  2. 文献翻译|Design of True Random Number Generator Based on Multi-stage Feedback Ring Oscillator(基于多级反馈环形振荡器的真随机数发生器设计)

    基于多级反馈环形振荡器的真随机数发生器设计 摘要 真随机数生成器(trng)在加密系统中起着重要的作用.本文提出了一种在现场可编程门阵列(FPGA)上生成真随机数的新方法,该方法以 多级反馈环形振荡器 ...

  3. 浅谈C#随机数发生器

    我们在做能自动生成试卷的考试系统时,常常需要随机生成一组不重复的题目,在.net Framework中提供了一个专门用来产生随机数的类System.Random. 对于随机数,大家都知道,计算机不 可 ...

  4. [nRF51822] 16、nRF51822的随机数生成器,及随机数生成器的一些知识(可以帮您补补随机数发生器的知识)

    1.前言 随机数生成器在通信.加密.图像传输等领域应用广泛,且一般起到关键性作用.我在最近设计的一个近场射频通信协议的碰撞避退算法的过程中,便对此有深深体会. 2.伪随机数发生器 随机数发生器一般包括 ...

  5. boost 随机数发生器

    Random     随机数 在很多应用中都需要使用随机数.本库力求提供一个高效的,通用的随机数库.boost库有多种随机数生成方式.先熟悉一下各种随机数生成器的概念. 数字生成器(Number Ge ...

  6. 玩转X-CTR100 l STM32F4 l RNG硬件随机数发生器

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器 STM32F4硬件随 ...

  7. QuantLib 金融计算——数学工具之随机数发生器

    目录 QuantLib 金融计算--数学工具之随机数发生器 概述 伪随机数 正态分布(伪)随机数 拟随机数 HaltonRsg SobolRsg 两类随机数的收敛性比较 如果未做特别说明,文中的程序都 ...

  8. CPP-STL:随机数发生器random_shuffle

    //--------------------------------------------------------------------------- #include <string.h& ...

  9. C++11随机数的正确打开方式

    C++11随机数的正确打开方式 在C++11之前,现有的随机数函数都存在一个问题:在利用循环多次获取随机数时,如果程序运行过快或者使用了多线程等方法,srand((unsigned)time(null ...

随机推荐

  1. 【转】 Pro Android学习笔记(三三):Menu(4):Alternative菜单

    目录(?)[-] 什么是Alternative menu替代菜单 小例子说明 Alternative menu代码 关于Category和规范代码写法 关于flags 多个匹配的itemId等参数 什 ...

  2. web攻击之六:DNS攻击原理与防范

    随着网络的逐步普及,网络安全已成为INTERNET路上事实上的焦点,它关系着INTERNET的进一步发展和普及,甚至关系着INTERNET的生存.可喜的是我们那些互联网专家们并没有令广大INTERNE ...

  3. MongoDB分析工具之一:explain()语句分析工具

    explain(),语句分析工具 MongoDB 3.0之后,explain的返回与使用方法与之前版本有了很大的变化,介于3.0之后的优秀特色和我们目前所使用给的是3.0.7版本,本文仅针对Mongo ...

  4. UDK编辑器 49条小提示

    转自:http://www.cnblogs.com/hmxp8/archive/2012/02/09/2343674.html Very Helpful~ 01. First time using t ...

  5. 在Golang中使用C语言代码实例

    转自:http://www.jb51.net/article/56720.htm cgo 使得在 Golang 中可以使用 C 代码. Hello World 为了有一个较为直观的了解,我们来看一个简 ...

  6. 最近一直是web前段,没什么意思,所以就不发资料了

    最近一直是web前段,没什么意思,所以就不发资料了 版权声明:本文为博主原创文章,未经博主允许不得转载.

  7. CentOS 7 配置 samba服务器

    一.在服务器端上安装软件并进行相关配置(以下操作需用用户root进行): 1.安装samba: yum -y install samba samba-client 2.启动服务并设置开机启动: sys ...

  8. Servlet编程实例 续1

    -----------------siwuxie095                                 在 LoginServlet 中,右键->Open Type Hierar ...

  9. DOS查看端口占用及杀掉进程命令

    转载自:http://www.cnblogs.com/rainman/p/3457227.html 1. 查看端口占用 在windows命令行窗口下执行: netstat -aon|findstr & ...

  10. LINQ中的陷阱--TakeWhile&SkipWhile

    在用TakeWhile,SkipWhile设置陷阱之前,我们先来看一看他们的兄弟Take和Skip: public static IEnumerable<T> Take<T>( ...