当前位置: 首页 > 编程日记 > 正文

[转]C++11 随机数学习

相对于C++ 11之前的随机数生成器来说,C++11的随机数生成器是复杂了很多。这是因为相对于之前的只需srand、rand这两函数即可获取随机数来说,C++11提供了太多的选择和东西。

随机数生成算法:
        随机数生成算法有很多,C++11之前的C/C++只用了一种。C++11则提供下面三种可供选择:

linear_congruential_engine线性同余法
mersenne_twister_engine梅森旋转法
substract_with_carry_engine滞后Fibonacci
        这三种算法,在C++11里面都是用模板的方式实现的。如果我们要使用这三个模板类的话,就必须自己实例化之。但这些实例化参数都是这些算法里面使用到的参数,如果不懂算法的原理的话,真的不知道需要用什么参数才能得到比较好的随机序列。所以我们这些卑微的码农是用不了这些模板类的。C++11标准也想到了这点,所以就帮我们预定义了一些随机数类,这些随机数类都是用比较好的参数实例化上面那三个模板类。注意:在C++11里面,把这些随机数生成器叫做引擎(engines)。

下图列出了一些实例化的随机数类:

当然具体用了哪些参数,我们是不用管的,直接用就行了。

在上图的左上角,还可以看到一个default_random_engine的类。它也是一个实例化的类。之所以不归入那三种算法,是因为它的实现是由编译器厂家决定的,有的可能用linear_congruential_engine实现,有的可能用mersenne_twister_engine实现。这种现象在C/C++中见多了。不过,对于其他的类,C++11是有明确规定用哪种算法和参数实现的。

好了,说了这么多还是上一个例子吧。

#include<iostream>
#include<random>usingstd::cout;
usingstd::endl;
usingstd::cin;intmain()
{std::default_random_engine random;for(int i = 0; i < 20; ++i)cout<<random()<<' ';cout<<endl;return 0;
}
//gcc编译器需要加上 –std=c++11 选项。

C++11中,随机数都是定义在random头文件中的。除了default_random_engine,其他的那些实例化随机数类的名字都是怪怪的,所以还是这个好用。从例子中可以看到,是通过operator ()函数来获取下一个随机数。
       对srand熟悉的码农们肯定发现,这里没有使用到随机数种子。其实这里使用了默认种子,默认种子的值可以通过这类的公共静态常量default_seed来获取。如果想为这个类设置自己的种子的话,那么可以通过在构造函数中传入一个参数。也可以在构造之后调用seed()成员函数设置种子。

产生均匀分布的随机数:
       上面例子产生的随机数会比较大,如果我们只想产生0到100的随机数。按照我们之前的做法是直接random()%100。这种做法是不好的。原因可以参见《Accelerated C++》的7.4.4节。

C++11也知道这一点,这就使得C++11的随机数更加复杂了。

我们平常说产生随机数,隐含是意思是产生均匀分布的随机数。学过概率论的同学都知道,除了均匀分布还有很多分布,比如正态分布、泊松分布等等。之前在网上看过网友怎么用rand()函数产生的随机数制作这些分布。现在这工作不用码农做了,C++11标准都提供了这些分布。

C++11提供的均匀分布模板类为:uniform_int_distribution和uniform_real_distribution。前一个模板类名字中的int不是代表整型,而是表示整数。因为它是一个模板类,可以用int、long、short等整数类型来实例化。后一个表示浮点数模板类,可以用float和double来实例化。使用例子如下:

#include<iostream>
#include<random>
#include<time.h>using std::cout;
using std::endl;
using std::cin;int main()
{std::default_random_engine random(time(NULL));std::uniform_int_distribution<int> dis1(0, 100);std::uniform_real_distribution<double> dis2(0.0, 1.0);for(int i = 0; i < 10; ++i)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));

如果uniform_int_distribution使用了无参构造函数,那么其随机数的范围是[0,numberic_limits<type>::max()],也就是0到对应实例化类型能表示的最大值。对于uniform_real_distribution的无参构造函数,则是[0, 1)。

mt19937

当你第一眼看到这玩意儿的时候

肯定禁不住吐槽:纳尼?这是什么鬼?

确实,这个东西鲜为人知,但是它却有着卓越的性能

简介

mt19937是c++11中加入的新特性

它是一种随机数算法,用法与rand()函数类似

但是具有速度快,周期长的特点(它的名字便来自周期长度:2^19937-1)

说的直白一点,我们都知道rand()在windows下生成的数据范围为0-32767

但是这个函数的随机范围大概在(maxint,+maxint)(−maxint,+maxint)(maxint为int类型最大值)

实例

这个东西用法非常简单

#include<random>
#include<ctime>
std::mt19937 rnd(time(0));
int main()
{printf("%lld\n",rnd());return 0;
}



概率分布类型:
        C++11提供的概率分布类型有下面这些:

均匀分布:

uniform_int_distribution          整数均匀分布

uniform_real_distribution        浮点数均匀分布

伯努利类型分布:(仅有yes/no两种结果,概率一个p,一个1-p)

bernoulli_distribution    伯努利分布

binomial_distribution     二项分布

geometry_distribution    几何分布

negative_biomial_distribution  负二项分布

Rate-based distributions:

poisson_distribution 泊松分布

exponential_distribution指数分布

gamma_distribution 伽马分布

weibull_distribution 威布尔分布

extreme_value_distribution 极值分布

正态分布相关:

normal_distribution        正态分布

chi_squared_distribution卡方分布

cauchy_distribution       柯西分布

fisher_f_distribution      费歇尔F分布

student_t_distribution t分布

分段分布相关:

discrete_distribution离散分布

piecewise_constant_distribution分段常数分布

piecewise_linear_distribution分段线性分布

这些概率分布函数都是有参数的,在类的构造函数中把参数传进去即可。

下面是一个泊松分布的例子

#include<iostream>
#include<random>
#include<time.h>
#include<iomanip>intmain()
{const int nrolls = 10000; // number ofexperimentsconst int nstars = 100;   // maximum number of stars to distributeint parameter = 4;std::minstd_rand engine(time(NULL));std::poisson_distribution<int>distribution(parameter);int p[20]={};for (int i=0; i<nrolls; ++i){int number = distribution(engine);if (number < 20)++p[number];}std::cout << "poisson_distribution"<<parameter<< std::endl;for (int i=0; i < 20; ++i)std::cout<<std::setw(2)<< i<< ": " << std::string(p[i]*nstars/nrolls, '*') <<std::endl;return 0;
}

某一个输出结果为:

可能大家都忘了泊松分布了,看一下下面的图吧

真正的随机数:
        C++11还提供了一个random_device随机数类。它并不是由某一个数学算法得到的随机序列,而是通过读取文件,读什么文件看具体的实现(Linux可以通过读取/dev/random文件来获取)。文件的内容是随机的,因为文件内容是计算机系统的熵(熵指的是一个系统的混乱程度)。也是当前系统的环境噪声,系统噪音可以通过很多参数来评估,如内存的使用,文件的使用量,不同类型的进程数量等等。Linux的熵来自键盘计时、鼠标移动等。

不过gcc好像并没有很好地实现这个类,我手里的Mingw4.9.0就不随机,每次运行都得到同样的序列。

对于C++11的随机类的更多用法可以参考这里。

参考:《C++标准库 ——自学教程与参考手册》(第2版)

《C++ Primer》(第5版)

http://blog.csdn.net/akonlookie/article/details/8223525

http://stackoverflow.com/questions/19665818/best-way-to-generate-random-numbers-using-c11-random-library?rq=1

http://hipercomer.blog.51cto.com/4415661/857870

转载于:https://www.cnblogs.com/wlzy/p/10547136.html

相关文章:

Linux Shell ssh登录脚本

Linux 登陆服务器敲命令太多,某时候确实不便,所以就用shell写了一个 我的blog地址: http://www.cnblogs.com/caoguo 一.说明 支持秘密和密钥两种格式用户名和密码都是写文件的,明文保存二.配置 密码文件配置:序号:IP:端口:用户:密码:说明 1:192.168.88.128:22:root:toor:虚拟机…

C# 温故而知新:Stream篇(二)

C# 温故而知新&#xff1a;Stream篇&#xff08;二&#xff09; TextReader 和StreamReader 目录&#xff1a; 为什么要介绍 TextReader&#xff1f; TextReader的常用属性和方法 TextReader 示例 从StreamReader想到多态 简单介绍下Encoding 编码 StreamReader 的定义及作用 S…

usaco Pollutant Control

第一问是求最小割。第二问求最小割中集合中边最少的集合的大小。 第三问求集合中边最少且字典序最小的边的下标。 第一问直接求最大流就能解&#xff0c;第二问将原来的边的容量都改为1&#xff0c;求出来的最大流就是元素最少的一个最小割的大小。 将容量都改为1之后&#xff…

洛谷P4705 玩游戏(生成函数+多项式运算)

题面 传送门 题解 妈呀这辣鸡题目调了我整整三天……最后发现竟然是因为分治\(NTT\)之后的多项式长度不是\(2\)的幂导致把多项式的值存下来的时候发生了一些玄学错误……玄学到了我\(WA\)的点全都是\(WA\)在\(2\)的幂次行里…… 看到这种题目二话不说先推倒 \[ \begin{aligned}…

blast程序 介绍 简介

每次找都挺麻烦&#xff0c;又记不住&#xff0c;于是抄下来&#xff1a; blastp:将待查询的蛋白质序列及其互补序列一起对蛋白质序列数据库进行查询&#xff1b;blastn:将待查询的核酸序列及其互补序列一起对核酸序列数据库进行查询&#xff1b;blastx:先将待查询的核酸序列按…

java泛型的实现和原理_java 泛型实现原理

泛型思想最早在C语言的模板(Templates)中产生&#xff0c;Java后来也借用了这种思想。虽然思想一致&#xff0c;但是他们存在着本质性的不同。C中的模板是真正意义上的泛型&#xff0c;在编译时就将不同模板类型参数编译成对应不同的目标代码&#xff0c;List和List是两种不同的…

java out of range_关于Parameter index out of range求解决办法

程序&#xff1a;提示参数越界&#xff0c;但我实在不知道我到底哪里越界了。明明该我那样写的嘛。求高手帮我看看&#xff0c;现在我是弄得我有气无力了&#xff01;要死了。在去死亡的路上等着你帮帮我&#xff01;Document : replyokCreated on : 2008-9-29, 6:05:31Autho…

FineReport——权限分配以及自定义首页

权限分配可以有两种方法&#xff0c;第一种方法是根据部门职位分配权限&#xff0c;第二种是根据角色分配权限&#xff1b; FR自带有三个JQ对象&#xff0c;用以保存用户名参数/角色参数/部门参数——$fr_username/$fr_authority/$fr_userposition 根据部门职位&#xff1a; 以…

去掉[]中的英文(正则表达式)C#

这个问题本来是以为信息科技大学的老师问蒋委员长的问题,蒋委员长用正则表达式完成了这个问题 1,问题的情况有哪些? abc[abc]abc,abc[-abc]abc,abc[一abc]abc,abc[一abc一]abc等等. 2,问题的解决目标? 写一个通用的方法来完成提出的问题. 3,解决方案 -->正则表达式方法 其…

Event Loop

事件队列 Javascript是单线程&#xff0c;单线程就意味着所有任务需要排队。然后会将所有任务分成两类&#xff1a;同步任务和异步任务&#xff01;同步任务&#xff1a;在主线程上执行的任务&#xff0c;只有前一个任务执行完成&#xff0c;才会执行后一个&#xff01;异步任务…

java makefile jar包_java makefile学习实践(编译的javac命令写在makefile中,运行命令java写在shell脚本中)...

学习makefile教程&#xff0c;ubuntu中文网1.写一个简单的java项目&#xff0c;不需要外部jar,用的简单的importjava.util.ArrayList;是可以从CLASSPATH环境变量中找到的&#xff0c;在javac阶段不需要特殊添加-cphellocatHellocat.javaimportjava.util.ArrayList;importjava.u…

Python字符编码详解

Python字符编码详解 转自http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html Python字符编码详解 本文简单介绍了各种常用的字符编码的特点&#xff0c;并介绍了在python2.x中如何与编码问题作战 &#xff1a;&#xff09; 请注意本文关于Python的内容仅适用于2.x&a…

《编写有效用例》读书笔记1

第一章 引言 本章主要介绍用例是什么样子的&#xff0c;并描述为什么不同的项目组需要采用不同 的用例编写风格以及在什么地方使用用例有利于做需求收集工作&#xff0c;也让我们了解 在编写用例之前&#xff0c;需要做哪些准备工作。 用例是代表系统中各个项目相关人员之间就系…

顺序结构,判断结构 if,switch

1&#xff1a;顺序结构&#xff1a;从上往下执行程序代码&#xff0c;为顺序结构 ---------------------------------------------------------------------- 2&#xff1a;判断结构&#xff1a; if 如果 判断是两个选择一个&#xff0c;要么对要么错 if中的条件表达式 返回…

php转换文字Unicode,php实现将中文转为unicode的方法

相关函数说明&#xff1a;iconv命令是用来转换文件的编码方式的&#xff0c;比如它可以将UTF8编码的转换成GB18030的编码&#xff0c;反过来也行。str_split() 函数把字符串分割到数组中。bin2hex() 函数把 ASCII 字符的字符串转换为十六进制值。字符串可通过使用 pack() 函数再…

kail安装和vmtools安装

因位太费劲我直接把我做的Word文档直接上传了&#xff0c;如果想安装可以下载&#xff0c;我就不麻烦在写一遍了&#xff0c;这个教程主要给小白讲的&#xff0c;大佬请绕过 kail安装教程.docx https://pan.wps.cn/l/sm43o7f 密码&#xff1a;f43341转载于:https://www.cnblogs…

Windows计数器做性能监控(window server 2008服务器)

使用Windows计数器 一、创建数据收集器集 二、创建数据收集器 三、使用数据收集器 1、修改数据收集器的属性 2、手动启用、手动停止数据收集器集 3、计划任务 4、在性能监视器中查看 一、性能监视器 Windows 服务器操作系统提供一个名为“性能监视器”的图形工具&#xff0c;可…

使用浏览器wpf应用程序时访问数据库需要报权限错误的解决方法

在这篇wpf教程中&#xff0c;如果选用浏览器wpf应用程序模板我遇到了 访问数据库时权限不够 不能打开连接 将项目属性的安全性中设置为完全信任后即解决 转载于:https://www.cnblogs.com/langu/archive/2012/03/29/2423620.html

gprs 神奇宝典java,2016联通笔试知识点大全

答&#xff1a;呼叫转移是指用户在工作忙或手机无网络等无法用本机接听电话的情况下&#xff0c;即可将来电设置呼叫转移到另一个号码上&#xff0c;实现号码转移。注&#xff1a;呼叫转移业务目前无需月功能费&#xff0c;用户设置呼叫转移后&#xff0c;如正常接听来电则按照…

内存管理器(二)边界标识法

边界标识算法 前言 首先说明&#xff0c;我们这里的内存管理器主要是以模拟各种内存分配算法为主&#xff0c;从内存申请一片内存然后根据我们所选定的数据结构和算法&#xff0c;实现程序的堆空间的分配&#xff0c;至于内存分配详情我们会在Linux内核内存管理的简单分析中探讨…

XDOC Office Server 开源了,Office文档完美转换为PDF

百度智能云 云生态狂欢季 热门云产品1折起>>> 项目地址&#xff1a;https://gitee.com/xdoc/xoffice XDOC是一个文档自动化平台&#xff0c;提供免费的Office文档生成服务。有用户提出要PDF格式&#xff0c;便于阅读、发布。在尝试了OpenOffice、WPS、微软Office、P…

js的defer属性

js的defer属性说明&#xff1a;<script src"js.js" type"text/javascript defer"defer"/>中defer的作用 给外链的js脚本添加defer"defer" 或 defer"true",使用defer属性可以让脚本在整个页面装载完成之后再解析&#xff0c…

怎么读取java文件,Java怎么读取文件

当前位置:我的异常网 J2SE Java怎么读取文件Java怎么读取文件www.myexceptions.net 网友分享于&#xff1a;2013-12-20 浏览&#xff1a;60次Java如何读取文件?源文件如下,小弟没有学过Java,下面是一段JAVA用RSA加密字符串的程序,命令行的形式是Java PublicExample ABC…

Android环境变量的设置(详细图解版)

Android环境变量的设置&#xff08;详细图解版&#xff09; 转载于:https://www.cnblogs.com/zhujiabin/p/4875182.html

用加密货币连接业务的6种方法

如今&#xff0c;区块链技术和加密货币已经变得更加接近传统业务。在某些情况下&#xff0c;商人们能够找到一种将传 统商业与新技术相结合的有价值的模式。事实上&#xff0c;进入加密货币市场有很多选择&#xff0c;本文将讨论6种主 要的合作方式。 创建加密货币平台是为了完…

extjs grid renderer用法

renderer可以格式化该列显示的数据格式或者按照你自定义的脚本显示最终数据样子&#xff08;我目前是这么理解的&#xff09; 先看下renderer: function()里的参数 var cm new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(),sm,{header:商品名称, dataIndex: name,render…

java50车架适合身高,【经验分享】身高与车架的选择

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼车架的长度&#xff1a;骑在车上&#xff0c;在正常握把时&#xff0c;眼睛、把立前端和前轮花鼓三点一线则说明车架长度正好&#xff0c;否则可通过更换不同长度的把立来调整长度。在Airborne网站上看到了度量身体个部位长度和计算…

从Android界面开发谈起(转)

原文地址&#xff1a;http://blog.csdn.net/nieweilin/article/details/5967815 这篇文章没有打算有一个很好的逻辑去介绍android的某个方面&#xff0c;全盘大致上就是我接触、了解android的ui开发后到现在的一些感想以及个人理解吧&#xff01; 全文可能会涉及到java、androi…

Android笔记之使用LocationManager获取经纬度

LocationManager.getLastKnownLocation(String provider)有可能返回null&#xff0c;概率还挺高 findViewById(R.id.llMain).setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {AndPermission.with(MainActivity.this).runtime().permissi…

Java虚拟机类加载机制

虚拟机类加载机制&#xff1a;虚拟机把描述类的数据从class文件加载到内存&#xff0c;并对数据进行校验、转换解析和初始化&#xff0c;最终形成可以被虚拟机直接使用的Java类型。 Java语言里&#xff0c;类型的加载和连接过程是在程序运行期间完成的。 类的生命周期&#xff…