17.4 Random Numbers(随机数)

程序使用rand()来生成谁技术,此函数生成的是伪随机数,每个随机数的范围在0到一个系统相关的最大数(至少为32767)之间。

 

C++通过定义在random中的随机数引擎类和随机数分布类来生成unsigned随机数。

引擎:生成随机unsigned整数序列

分布:使用引擎返回特定概率分布的随机数

 

C++程序不应该使用库函数rand,而应使用default_random_engine类和恰当的分布类对象。

#include <iostream>
#include <random>

using namespace std;

int main()
{
    default_random_engine e;
    for (int i = 0; i < 10; i++)
        cout << e() << ends;

    return 0;
}

上面是随机数引擎的输出,一般不能直接使用。

式子 说明
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

 

通过分布类型对象,获得指定范围的数。

#include <iostream>
#include <random>

using namespace std;

int main()
{
    uniform_int_distribution<unsigned> u(0, 9);
    default_random_engine e;
    for (int i = 0; i < 10; i++)
        cout << u(e) << ends;

    system("PAUSE");
    return 0;
}

 

类似引擎类型,分布类型也是函数对象类。

注意:我们传递给分布对象的是引擎对象本身,即u(e)

 

随机数发生器:分布对象和引擎对象的组合。

 

#include <iostream>
#include <string>
#include <random>
#include <vector>
#include <ctime>

using namespace std;

vector<unsigned> func() {
    uniform_int_distribution<unsigned> u(0, 9);
    default_random_engine e(time(0));
    vector<unsigned> vec;
    for (int i = 0; i < 10; ++i) {
        vec.push_back(u(e));
    }

    return vec;
}

vector<unsigned> func1() {
    static uniform_int_distribution<unsigned> u(0, 9);
    static default_random_engine e;
    vector<unsigned> vec;
    for (int i = 0; i < 10; ++i) {
        vec.push_back(u(e));
    }

    return vec;
}

int main()
{
    vector<unsigned> vec1(func()), vec2(func());
    cout << ((vec1 == vec2) ? "相同" : "不同") << endl;
    for (auto& i : vec1) {
        cout << i << " ";
    }
    cout << endl;
    for (auto& i : vec2) {
        cout << i << " ";
    }
    //func();
    vector<unsigned> vec3(func1()), vec4(func1());
    cout << ((vec3 == vec4) ? "相同" : "不同") << endl;
    for (auto& i : vec3) {
        cout << i << " ";
    }
    cout << endl;
    for (auto& i : vec4) {
        cout << i << " ";
    }
    cout << endl;
    uniform_real_distribution<double> f(0,1);
    default_random_engine r(time(NULL));

    vector<double> vec5, vec6;
    for (int i = 0; i < 10; ++i) {
        vec5.push_back(f(r));
    }
    for (auto& i : vec5) {
        cout << i << " ";
    }
    cout << endl;
    for (int i = 0; i < 10; ++i) {
        vec6.push_back(f(r));
    }
    for (auto& i : vec6) {
        cout << i << " ";
    }

    system("PAUSE");
    return 0;
}

 

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

 

选择一个好的种子,与生成好的随机数所涉及的其他大多数事情相同,是极其困难的。可能最常用的方法是调用系统函数time。这个函数定义在头文件ctime中,它返回从一个特定时刻到当前经过了多少秒。函数time接受单个指针参数,它指向用于写入时间的数据结构。如果此指针为空,则函数简单地返回时间。

default_random_engine e(time(NULL));

由于time返回以秒计的时间,因此这种方式只适用于生成种子的间隔为秒级或更长的应用。

 

如果程序作为一个自动过程的一部分反复运行,将time的返回值作为种子的方式就无效了;它可能多次使用的都是相同的种子。

 

使用normal_distribution生成浮点值。

#include <string>
#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>
#include <random>

#define N 200
using namespace std;

int main()
{
    default_random_engine e(time(NULL));
    normal_distribution<> n(4, 1.5);//正态分布,均值为4,标准差为1.5

    vector<unsigned> vec(9);

    for (size_t i = 0; i < N; ++i) {
        unsigned num = lround(n(e));//取离浮点数最近的整数
        if (num < vec.size())
            ++vec[num];
    }

    for (size_t i = 0; i < vec.size(); ++i)
        cout << vec[i] << ":" << string(vec[i], '*') << endl;

    system("PAUSE");
    return 0;
}

 

 

bernoulli_distribution类总是返回一个bool值

posted @ 2019-02-27 22:12  Hk_Mayfly  阅读(408)  评论(0)    收藏  举报