zoukankan      html  css  js  c++  java
  • 随机值获取—random

    如何利用 random 库中的组件生成符合条件的随机数。

    随机数引擎类是可以独立运行的随机数发生器,它以均匀的概率生成某一类型的随机数,但无法指定随机数的范围、概率等信息。因此,它也被称为“原始随机数发生器”,由于不能指定生成随机数的范围,它通常不会被单独使用。

    随机数分布类是一个需要于随机数引擎类的支持才能运行的类,但是它能根据用户的需求利用随机数引擎生成符合条件的随机数,例如某一区间、某一分布概率的随机数。

    随机数引擎类都支持的操作如下:

    名称功能
    Engine e 创建一个引擎。
    Engine e(s) 创建一个引擎,并用 s 作为种子。
    e.seed(s) 使用种子 s 充值 e 的状态。
    e.min( ), e.max( ) e 能生成的最小值和最大值。
    e.discard(u) 将 e 推进 u 步(u 的类型为 unsigned long long)。

    随机数分布类共有的操作:

    名称功能
    U u 创建一个分布类 u 。
    u(e) 用随机数引擎 e 生成随机数(u 代表随机数分布类)。
    u.min( ) u 能生成的最小值。
    u.max( ) u 能生成的最大值。
    u.reset( ) 重置 u 的状态,使随后 u 生成的值不受之前的值影响 。

    随机非负数——default_random_engine


    default_random_engine 是一个随机数引擎类。它定义的调用运算符返回一个随机的 unsigned 类型的值。

    因此,若想生成 10 个随机非负数并输出,程序可以这么写:

    #include <iostream>
    #include <random>
    using namespace std;
    
    int main( ){
        default_random_engine e;
        for(int i=0; i<10; ++i)
            cout<<e( )<<endl;
        return 0;
    }
    

    在我们的系统中,测试结果为:

    16807
    282475249
    1622650073
    984943658
    1144108930
    470211272
    101027544
    1457850878
    1458777923
    2007237709
    

    可以看出,还是比较“随机”的。

    当然,default_random_engine 也只是一个伪随机数发生器,如果在运行一次程序,得到结果将还是这几个数。

    若想令每次运行程序时的生成结果不同,可以为其设置较为随机的种子,比如当前系统的时间。

    特定范围的非负数——uniform_int_distribution


    uniform_int_distribution 是一个随机数分布类,也是个模板类,模板参数为生成随机数的类型(不过只能是 int、unsigned、short、unsigned short、long、unsigned long、long long、unsigned long long 中的一种)。它的构造函数接受两个值,表示随机数的分布范围(闭区间)。

    因此,一个生成 0 到 9 的随机数程序可以这么写:

    #include <iostream>
    #include <random>
    using namespace std;
    
    int main( ){
        default_random_engine e;
        uniform_int_distribution<unsigned> u(0, 9);
        for(int i=0; i<10; ++i)
            cout<<u(e)<<endl;
        return 0;
    }
    

    在我们的系统中,它的生成结果为:

    0     
    1     
    7     
    4     
    5     
    2     
    0     
    6     
    6     
    9     
    

    随机浮点数——uniform_real_distribution


    uniform_real_distribution 是一个随机数分布类,它也是模板类,参数表示随机数类型(可选类型为 float、double、long double)。构造函数也需要最大值和最小值作为参数。

    下面是一个生成 10 个 0~1 之间的随机浮点数的例子:

    #include <iostream>
    #include <random>
    using namespace std;
    
    int main( ){
        default_random_engine e;
        uniform_real_distribution<double> u(0.0, 1.0);
        for(int i=0; i<10; ++i)
            cout<<u(e)<<endl;
        return 0;
    }
    

    在我们的系统上的结果为:

    0.131538
    0.45865
    0.218959
    0.678865
    0.934693
    0.519416
    0.0345721
    0.5297
    0.00769819
    0.0668422
    

    随机布尔值——bernoulli_distribution


    bernoulli_distribution 是一个分布类,但它不是模板类。它的构造函数只有一个参数,表示该类返回 true 的概率,该参数默认为 0.5 ,即返回 true 和 false 的概率相等。

    下面是一个生成 10 个随机布尔值的例子:

    #include <iostream>
    #include <random>
    using namespace std;
    
    int main( ){
        default_random_engine e;
        bernoulli_distribution u;
        for(int i=0; i<10; ++i)
            cout<<u(e)<<endl;
        return 0;
    }
    

    在我们的系统上的结果为:

    1
    1
    1
    0
    0
    0
    1
    0
    1
    1
    

    总结


    常用的随机数类如下:

    • default_random_engine:随机非负数(不建议单独使用)。
    • uniform_int_distribution:指定范围的随机非负数。
    • uniform_real_distribution:指定范围的随机实数。
    • bernoulli_distribution:指定概率的随机布尔值。

    事实上,random 库的功能极其丰富,其中的随机数引擎不止有 default_random_engine 一个,分布类也远远不止上述三个。它还能进行泊松分布、正态分布、抽样分等高级的随机数功能,想详细了解这些内容请去查阅其他资料。我可能要等好久才能把这些内容补上。

    C++11中的random类

    random类是C++11中增加的类,该类可以用于生成随机数,具有C语言中rand生成伪随机数的功能,但其功能更强大。原生支持生成浮点数,及分布类。 

    随机数发生器主要由分布对象和随机数引擎对象组成。其中随机数引擎用于根据随机数种子来产生随机数,分布对象对产生的随机数根据需求进行分布。
    random中定义了多种随机数引擎及分布类型,常用的引擎是默认伪随机数引擎类default_random_engine,常用的分布类有产生整型分布的uniform_int_distribution,产生浮点型的分布uniform_real_distribution。 

    举例

    该程序输出15个double类型的随机数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <random>
    #include <iostream>
    #include <ctime>

    //该函数接受三个参数分别指定随机数范围和种子,返回double
    double random_unint(unsigned int min, unsigned int max, unsigned int seed = 0)
    {
    static std::default_random_engine e(seed);
    static std::uniform_real_distribution<double> u(min, max);
    return u(e);
    }

    int main(void)
    {
    for (int i = 0; i < 15; ++i) {
    std::cout << random_unint(0, 15, time(NULL)) << " ";
    }
    std::cout << std::endl;
    return 0;
    }

    需要注意

    1.一个给定的随机数发生器一直会生成相同的随机数序列。一个函数如果定义了局部的随机数发生器,应该将其(包括引擎和分布对象)定义为static的,否则每次调用函数都会生成相同的序列。也就是说定义成static后每次调用还是之前那个发生器,第一次调用产生一批随机数,再次调用将产生接下来的随机数,否则每次调用产生的都是最前面的那些随机数。

    2.依然需要使用time来做为种子产生每个不同时刻都不同的随机序列,但由于time默认返回的是以秒计的时间,所以有可能多次使用的都是相同的种子。 

    伪随机数引擎

    1.随机数引擎支持的操作如下: 

    • Engine e; //默认构造函数,使用该引擎类型的默认种子
    • Engine e(s); //使用整型s做为种子
    • e.seed(s); //使用整型s重置引擎状态
    • e.min(); //返回此引擎所能生成的最小和最大值
    • e.max();
    • Engine::result_type //此引擎生成的类型(unsigned)
    • e.discard(u); //将引擎推进u步,u为unsigned long long类型 

    2.随机数引擎使用

    1
    2
    std::default_random_engine e;   //生成随机的无符号数
    std::cout << e(); //通过()调用对象生成下一个随机数并输出

    作者:zhaosiyi
    链接:https://www.jianshu.com/p/05863a00af8d
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    POJ3928 Pingpong(统计比 K 小的个数 + 树状数组)
    C++ Primer Plus读书笔记
    HDU1698Just a Hook(线段树 + 区间修改 + 求和)
    POJ3468A Simple Problem with Integers(区间加数求和 + 线段树)
    POJ2528Mayor's posters(离散化 + 线段树)
    约瑟夫环
    编写一个JavaWeb项目
    四则运算在线答题系统
    JAVA项目中的常用的异常处理情况
    第八周动手动脑
  • 原文地址:https://www.cnblogs.com/xiaofeiIDO/p/8581178.html
Copyright © 2011-2022 走看看