c++—-随机数算法

c++—-随机数算法    本文转载:http://blog.csdn.net/luotuo44/article/details/33690179     相对于C++11之前的随机数生成器来说,C++11的随机数生成器是复杂了很多。这是因为相对于之前的只需srand、rand这两函数即可获取随机数来说,C++11提供了太多的选择和东西。 随机数生成算法:   &.

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

        本文转载:http://blog.csdn.net/luotuo44/article/details/33690179

        相对于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)。

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

        c++----随机数算法

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

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

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


 
 
 
  1. #include<iostream>
  2. #include<random>
  3. usingstd:: cout;
  4. usingstd:: endl;
  5. usingstd:: cin;
  6. intmain()
  7. {
  8. std::default_random_engine random;
  9. for( int i = 0; i < 20; ++i)
  10. cout<<random()<< ' ';
  11. cout<< endl;
  12. return 0;
  13. }
  14. //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来实例化。使用例子如下:


 
 
 
  1. #include<iostream>
  2. #include<random>
  3. #include<time.h>
  4. using std:: cout;
  5. using std:: endl;
  6. using std:: cin;
  7. int main()
  8. {
  9. std:: default_random_engine random(time(NULL));
  10. std::uniform_int_distribution< int> dis1( 0, 100);
  11. std::uniform_real_distribution< double> dis2( 0.0, 1.0);
  12. for( int i = 0; i < 10; ++i)
  13. cout<<dis1(random)<< ' ';
  14. cout<< endl;
  15. for( int i = 0; i < 10; ++i)
  16. cout<<dis2(random)<< ' ';
  17. cout<< endl;
  18. return 0;
  19. }

        可以看到,在uniform_int_distribution的构造函数中,参数说明了随机数的范围。uniform_int_distribution的随机数的范围不是半开范围[  ),而是[  ],对于uniform_real_distribution却是半开范围[  )。也是就是说上面的例子中,能产生100,但不会产生1.0。不得不说,这颠覆了之前的认识。对于default_random_engine来说,其产生的随机数范围是在[min(), max()]之间,其中min()和max()为它的两个成员函数。同样,也是非半开范围。对于浮点数,如果真的是想产生[0.0, 1.0]范围的数,可以使用


 
 
 
  1. #include<cmath>
  2. #include<cfloat>
  3. 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)。

 

概率分布类型:

        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分段线性分布

 

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

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


 
 
 
  1. #include<iostream>
  2. #include<random>
  3. #include<time.h>
  4. #include<iomanip>
  5. intmain()
  6. {
  7. const int nrolls = 10000; // number ofexperiments
  8. const int nstars = 100; // maximum number of stars to distribute
  9. int parameter = 4;
  10. std:: minstd_rand engine(time(NULL));
  11. std::poisson_distribution< int>distribution(parameter);
  12. int p[ 20]={};
  13. for ( int i= 0; i<nrolls; ++i)
  14. {
  15. int number = distribution(engine);
  16. if (number < 20)
  17. ++p[number];
  18. }
  19. std:: cout << "poisson_distribution"<<parameter<< std:: endl;
  20. for ( int i= 0; i < 20; ++i)
  21. std:: cout<< std::setw( 2)<< i<< ": " << std:: string(p[i]*nstars/nrolls, '*') << std:: endl;
  22. return 0;
  23. }

        某一个输出结果为:

        c++----随机数算法

 

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

            c++----随机数算法

真正的随机数:

        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://javaforall.net/158926.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • android autosize原理,(原创)AndroidAutoSize屏幕适配工具介绍[通俗易懂]

    android autosize原理,(原创)AndroidAutoSize屏幕适配工具介绍[通俗易懂]屏幕适配是我们在开发中经常会遇到的一个问题不同的机型有不同的屏幕尺寸和密度现在市场上已经有不少屏幕适配的解决方案今天就来介绍一个我自己觉得不错的AutoSize这是是一个Android端可以根据设备不同屏幕尺寸自动适配宽高的工具特点是使用起来非常简单。作者写的介绍它网站有:https://www.jianshu.com/p/4aa23d69d481代码位置:https://github.com/J…

    2022年6月6日
    380
  • python面试题目及答案(数据库常见面试题及答案)

    Python是目前编程领域最受欢迎的语言。在本文中,我将总结Python面试中最常见的50个问题。每道题都提供参考答案,希望能够帮助你在2019年求职面试中脱颖而出,找到一份高薪工作。这些面试题涉及Python基础知识、Python编程、数据分析以及Python函数库等多个方面。Q1、Python中的列表和元组有什么区别?Q2、Python的主要功能是什么?Python是一种解释型…

    2022年4月17日
    65
  • keras自带数据集(横线生成器)

    原文地址:AdetailedexampleofhowtousedatageneratorswithKeras引言在使用kears训练model的时候,一般会将所有的训练数据加载到内存中,然后喂给网络,但当内存有限,且数据量过大时,此方法则不再可用。此博客,将介绍如何在多核(多线程)上实时的生成数据,并立即的送入到模型当中训练。工具为keras。Tu…

    2022年4月15日
    57
  • Photoshop快捷键大全_alt快捷键大全常用

    Photoshop快捷键大全_alt快捷键大全常用察看图像类别  说明:: —Shift键  :—空格键       *—在Imageready中不适用  §—只在Imageready中可用动作结果双击工具箱::或Ctrl+0 使图像最大限度在当前窗口中完整显示双击工具箱::或Alt+Ctr

    2022年9月29日
    0
  • Matlab求解非线性规划(fmincon函数的使用)[通俗易懂]

    Matlab求解非线性规划(fmincon函数的使用)[通俗易懂]最近写文章需要用到fmincon函数(寻找约束非线性多变量函数的最小值)做优化,于是抽空学习一下;按照惯例,继续开个博文记录一下学习的过程。

    2022年5月30日
    54
  • 把旧光驱改CD播放机的方法

    把旧光驱改CD播放机的方法  随着我们自己PC机各项配件的不断升级,或多或少都会淘汰下来一些旧配件。它们是否真的就只能躺在角落里睡大觉呢?能够最大限度利用上这些曾经为我们驰骋沙场,立下赫赫战功的战将吗?那么就要看我们自己是否足够勤劳了。下面我们就以PC机中比较容易更新换代的光驱为例,来看看怎么让它恢复第二春吧。  先天条件  通常来说,光驱“惨遭”淘汰的时候读盘能力已经很弱了,但机械上一般都没有损坏,特别是CD是完…

    2022年4月29日
    55

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号