c++ 中的随机数

  在 C++ 程序中,在新标准出现之前,C 和 C++ 都依赖一个简单的 C 库函数 rand 来生成随机数,但是,这个函数生成的是均匀分布的伪随机数,每个随机数的范围在 0 和一个系统相关的最大值(至少为 32767)之间。

  rand 函数有一些问题:即使不是大多数,也有很多程序需要不通范围的随机数。一些应用需要随机浮点数。一些程序需要非均匀分布的随机数。而在编写程序为了解决这些通常会转换 rand 生成的随机数的范围、类型或者是分布时,常常会引入非随机性。

  在 C++ 11 标准中,定义在头文件 random 中的随机数库通过一组协作的类来解决这些问题,主要用到的是两个类:

  • 随机数引擎类(random-number engines)
  • 随机数分布类(random-number distribution)

其中,一个引擎类可以生成 unsigned 随机数列,一个分布使用一个引擎类生成指定类型的,在给定范围内的,服从指定概率分布的随机数。


1. 随机数引擎和分布

  随机数引擎是函数对象类,他们定义了一个调用运算符,该运算符不接受参数并返回一个随机的 unsigned 整数。我们可以通过调用一个随机数引擎对象来生成原始随机数。

default_random_engine e;    // 生成随机无符号数
for(size_t i=0; i<10; i++)// e() “调用”对象来生成下一个随机数cout << e() <<endl;

在上面这几行的代码中,定义了一个名为 e 的 default_random_engine 的对象。在 for 循环内,我们调用对象 e 来获得下一个随机数。

1.1 分布类型和引擎

  为了得到一个在指定范围内的数,我们一用一个分布类型的对象:

//生成 0 到 9 之间(包含)均匀分布的随机数
uniform_int_distribution<unsigned> u(0,9);
default_random_engine e;    // 生成无符号随机整数
for (size_t i =0;i<10; i++)// 将 u 作为随机数源// 每个调用返回在指定范围内并服从均匀分布的值cout<<u(e)<<" ";
cout<< endl;

上面的代码输入如下:

0 1 7 4 5 2 0 6 6 9

  上面的程序中,我们将 u 定义为 uniform_int_distribution<unsigned> 。这种类型生成均匀分布的 unsigned 值。当我们定义一个这种类型的对象时,可以提供想要的最小值和最大值。在上面这段代码中,u(0,9) 表示我们希望得到 0 到 9 之间(包含)的数。随机数分布类会使用包含的范围,从而我们可以得到给定整形的每个可能值。

  类似引擎类型,分布类型也是函数对象类。分布类型定义了一个调用运算符,它接受一个随机数引擎作为参数。分布对象使用它的引擎参数生成随机数,并将其映射到指定的分布。

  传递给分布对象的是引擎对象本身,也就是 u(e),如果我们将调用写为 u(e()),含义就变为将 e 生成的下一个值传递给 u,这会导致一个编译错误。我们传递的是引擎本身,而不是他生成的下一个值,原因是某些分布可能需要调用引擎多次才能得到一个值。

1.2 使用引擎生成一个数值序列

  随机数发生器有一个特性,也就是即使生成的树看起来是随机的,但是对于一个给定的发生器,每次运行程序它都会返回相同的数值序列。序列不变这一事实在 调试 的时候十分有用,但是另一方面,使用随机数发生器的程序也必须考虑到这一特性。

  下面介绍一个例子,需要一个函数生成一个 vector,包含 100 个均匀分布在 0 到 9 之间的随机数。一种错误的方法是使用下面的代码:

vector<unsigned >bad_randVec()
{default_random_engine e;uniform_int_distribution<unsigned >u(0,9);vector<unsigned >ret;for(size_t i = 0;i<100;i++)ret.push_back(u(e));return ret;
}
// 但是 每次调用这个函数都会返回相同的 vector
vector<unsigned >v1(bad_randVec());
vector<unsigned >v2(bad_randVec());
// 将会打印输出 equal
cout << ((v1==v2) ? "equal" : "not equal") << endl;

上面这段代码会输出 equal,因为 vector v1 和 v2 具有相同的值。

正确的定义方法是 将引擎和关联的分布对象定义为 static 的

 vector<unsigned >good_randVec()
{// 由于我们希望引擎和分布对象保持状态,因此应该将他们定义为// static 的,从而每次调用都生成新的数static default_random_engine e;static uniform_int_distribution<unsigned > u(0,9);vector<unsigned > ret;for(size_t i = 0; i<100;i++)ret.push_back(u(e));return ret;
}

由于 e 和 u 都是 static 的,因此它们在函数调用之间会保持住状态。第一次调用会使用 u(e) 生成的序列中的前 100 个随机数,第二次调用会获得接下来 100 个。以此类推。

  注意,一个给定的随机数发生器已知会生成相同的随机数序列。一个函数如果定义了局部的随机数发生器,应该将其(包括引擎和分布对象)定义为 static 的。否则,每次调用函数都会生成相同的序列。

1.3 设置随机数发生器种子

  随机数发生器会生成相同的随机数序列这一特性在调试中很有用。但是,一旦我们的程序调试完毕,我们通常希望每次运行程序都会生成不同的随机结果,可以通过提供一个种子(seed)来达到这个目的。种子就是一个数值,殷勤可以利用它从序列中一个新位置重新开始生成随机数。

  为引擎设置种子有两种方式:

C++11生成随机数(random库)相关推荐

  1. 生成随机数random学习之uniform_int_distribution,uniform_real_distribution

    在程序开发过程中,有时我们需要用到随机数,如果自己手写一个随机数容易引用重复,而c++11已经提供了一个生成随机数的库random,并且就可设置随机数的范围和类型,下面我们来学习使用两个最常用的随机数 ...

  2. python生成随机数random.randint()随机取值的概率

    python生成随机数random.randint() 1.random.randint(参数1,参数2) 参数1.参数2必须是整数 函数返回参数1和参数2之间的任意整数 2.random.unifo ...

  3. Python如何生成随机数——random随机数模块的应用

    文章目录 1.随机生成0-1的浮点数random.random 2.随机生成指定范围内的浮点数random.uniform 3.随机生成指定范围整数random.randint 4.随机从给定集合中生 ...

  4. python生成随机数random操作_Python random生成随机数示例

    代码中经常有一些生成随机数的需求.特意整理了一下Python中random模块的一些相关使用方法示例. python生成随机数 随机整数: >>> import random > ...

  5. php生成随机数random,PHP生成随机数的方法实例分析

    通常情况下,当我们要生成一个随机字符串时,总是先创建一个字符池,然后用一个循环和mt_rand()或rand()生成php随机数,从字符池中随机选取字符,最后拼凑出需要的长度. function ra ...

  6. python生成随机数—random模块

    random 模块包括返回随机数的函数,可以用于模拟或者任何产生随机输出的程序. random.random()    返回随机生成的一个实数,它在[0,1)范围内 random.randint(a, ...

  7. random库:Python随机数的生成与应用

    目录 前言 生成随机数 种子 random.sample 随机元素 SystemRandom 非均匀分布 正态分布 近似分布 前言 在实际的开发中,经常会用到随机数生成.而random库专用于随机数的 ...

  8. python标准库生成随机数_Python3标准库:random伪随机数生成器

    1. random伪随机数生成器 random模块基于Mersenne Twister算法提供了一个快速伪随机数生成器.原来开发这个生成器是为了向蒙特卡洛模拟生成输入,Mersenne Twister ...

  9. java生成随机数random_Java获取随机数Random

    随机数在实际中使用很广泛,比如要随即生成一个固定长度的字符串.数字.或者随即生成一个不定长度的数字.或者进行一个模拟的随机选择等等.Java提供了最基本的工具,可以帮助开发者来实现这一切. 一.Jav ...

最新文章

  1. registry ---------仓库 -----------------镜像
  2. 中科院德州扑克AI获卓越论文奖!AAAI 2022开奖,吴恩达获纪念讲座奖
  3. 【Flask】Nginx+Gunicorn+Supervisor部署一个Flask项目:步骤总结
  4. list取数据_Day.5利用Pandas做数据处理(二)
  5. LeetCode 1071. 字符串的最大公因子(字符串的最大公约数)
  6. BZOJ3928 [Cerc2014] Outer space invaders
  7. h5自定义相机界面_有没有什么比较好用的H5小程序?
  8. 电脑安装系统安装不上的几个问题(解决)
  9. 什么是JavaSE/JavaEE/JavaME?
  10. 新能源整车控制器VCU开发过程分享
  11. 条码打印软件之PDF的拆分合并功能
  12. ORA-01652(永久表空间临时段不能扩展情况分析)
  13. 川普撞脸希拉里(基于 OpenCV 的面部特征交换)-1
  14. 油气田工业控制系统现状
  15. 一对一视频直播系统开源一对一视频交友源码程序
  16. 织梦php 文章采集规则,dedecms采集怎么用
  17. tomcat(一个牛人写的文章,自己看)
  18. 顺通订单及客户档案资料管理系统
  19. Adaptive AUTOSAR (AP) 平台设计(6)——通信管理
  20. 戴尔(DELL)台式机optiplex 7080安装centos经验

热门文章

  1. Eclipes和Myeclipse插件安装方法
  2. android 载入svg动画,实例讲解使用SVG制作loading加载动画的方法
  3. 纯代码开发c# ui_UI代码挑战#1-心跳
  4. Typescript泛型与implements子句
  5. LINUX:Ubuntu重装虚拟机后无法拖拽文件的解决方法
  6. UE4 UE4使用小技巧——使用上帝视角运行游戏
  7. 宽带服务器无响应678,宽带连接错误678怎么办 是什么原因导致的【解决方法】...
  8. 新的开始之Win7、CentOS 6.4 双系统 硬盘安装
  9. java实现牛牛算法
  10. 聚宽JQData说明书