c++11 随机数random

大兔子大兔子 提交于 2020-03-07 08:08:50

c++11提供的<random>实现了随机数库,它通过随机数引擎类(random_number_engines)产生随机数序列,随机数分布类(random-number distribution)使用随机数引擎生成服从特定概率分布的随机数。

让我们看一个简单的例子:

#include <iostream>
#include <random>

using std::cout; using std::endl;
using std::default_random_engine;

int main()
{
    default_random_engine e;
    for (size_t i = 0; i < 10; ++i) //生成十个随机数
       cout << e() << endl;
    cout << "Min random:" << e.min() << endl; //输出该随机数引擎序列的范围
    cout << "Max random:" << e.max() << endl;
    return 0;
}

生成的随机数结果:

12

在例子中,随机数类是定义在std命名空间的,所以要声明。随机数引擎是函数对象,这就是为什么使用e()去生成随机数。程序每次运行都会生成相同的随机数序列,这在一定程度有利于程序的调试,但我们有时需要每一次运行产生的随机数序列都是不同的。我们可以通过设置随机数引擎的种子来改变引擎的状态,没有改变时是使用默认的随机数种子,这就是为什么每一次都生成同样的随机数序列。从结果我们可以知道,默认的种子生成随机数范围在1-2147483646之间。

#include <iostream>
#include <random>

using std::cout; using std::endl;
using std::default_random_engine;

int main()
{
    default_random_engine e; //或者直接在这里改变种子 e(10) 
    e.seed(10); //设置新的种子
    for (size_t i = 0; i < 10; ++i)
       cout << e() << endl;
    cout << "Min random:" << e.min() << endl;
    cout << "Max random:" << e.max() << endl;
    
    return 0;
}

设置新的种子后结果如下:

12

在结果可以看出,生成随机数序列不同了。在这里范围还是一样的,那么怎么去改变生成的范围呢?这时就可以使用随机数分布类了。

 

#include <iostream>
#include <random>

using std::cout; using std::endl;
using std::default_random_engine;
using std::uniform_int_distribution;
    
int main()
{
    default_random_engine e; 
    uniform_int_distribution<unsigned> u(0, 9); //随机数分布对象 
    for (size_t i = 0; i < 10; ++i)  //生成范围为0-9的随机数序列 
       cout << u(e) << " ";
    cout << endl;
    
    return 0;
}

结果如下:

12

这里要注意的这个序列也是每次运行程序相同的,因为分布对象将随机数引擎作为它的参数,分布对象使用它的引擎参数生成随机数,并将其映射到指定的分布。

---------------------------------------------------------------------------------------------------------------------------------------

现在,让我更深入一点吧,在图形上很多时候都要使用0.0-1.0的值(颜色)作为数据,那么怎么生成这样的序列呢?跟刚才那样,我们可以使用分布区定义范围。

#include <iostream>
#include <random>

using std::cout; using std::endl;
using std::default_random_engine;
using std::uniform_real_distribution;
    
int main()
{
    default_random_engine e; 
    uniform_real_distribution<double> u(0, 1); //随机数分布对象 
    for (size_t i = 0; i < 5; ++i)  //生成范围为0.0-1.0的随机数序列 
       cout << u(e) << " ";
    cout << endl;
    
    return 0;
}

结果:

12

在这里分布类改变了类型,采用的是real实数类型的分布类,实例化为<double>,生成0.0-1.0的double随机数序列。如果你想要获得分布类范围的端点,只要简单的成员函数min()和max()就可以了。

 

随机数的重要性质是随机分布,但是我们也可以生产非均匀分布的随机数序列。

下面的例子生成符合正态分布的随机数序列:

#include <iostream>
#include <random>
#include <vector>
#include <string>
 
using std::cout; using std::endl;
using std::default_random_engine;
using std::normal_distribution;
using std::vector; using std::string;
    
int main()
{
    default_random_engine e; 
    vector<unsigned> vals(9);
    normal_distribution<> n(4, 1.5); //正态分布,大部分生成的随机数落在0-8之间 
    for (size_t i = 0; i != 200; ++i)  
    {  unsigned v = lround(n(e)); //舍入到最近整数 
       if (v < vals.size())
          ++vals[v];        //统计0-8数字出现的次数 
    }
    for (decltype(vals.size()) i = 0; i != vals.size(); ++i) 
       cout << i << ": " << string(vals[i], '#') << endl;

    return 0;
}

结果:

12

 更多资料可看:C++Primer 5th

或者 :http://www.cplusplus.com/reference/random/?kw=random

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!