C++11:隨機(jī)數(shù)庫

1、介紹

在C++11新標(biāo)準(zhǔn)之前, 我們程序都是依賴于一個(gè)簡單的C庫函數(shù)rand來生成隨機(jī)數(shù)。此函數(shù)生成均勻分布的偽隨機(jī)數(shù),每個(gè)隨機(jī)數(shù)的范圍在0和一個(gè)系統(tǒng)相關(guān)的最大值之間。

C++11的頭文件random中有一組隨機(jī)數(shù)庫通過一組協(xié)作的類來解決這些問題:隨機(jī)數(shù)引擎類和隨機(jī)數(shù)分布類。

2、隨機(jī)數(shù)引擎和分布的使用

隨機(jī)數(shù)引擎的操作:

Engine e;     //默認(rèn)構(gòu)造函數(shù),使用該引擎類型默認(rèn)的種子
Engine e(s);  //使用整型值s作為種子
e.seed(s);  //使用種子s重置引擎的狀態(tài)
e.min();  //此引擎可生成的最小值
e.max(); //此引擎可生成的最大值
Engine::result_type; //此引擎生成的unsigned整型類型
e.discard(u);  //將引擎推進(jìn)u步; u的類型為unsigned long long

調(diào)用隨機(jī)數(shù)引擎的原始隨機(jī)數(shù):

    default_random_engine dre;
    for (int i = 0; i < 10; ++i)
        cout << dre() << endl;

大多數(shù)場合下隨機(jī)數(shù)引擎輸出的原始隨機(jī)數(shù)是不能直接使用的,需要進(jìn)行轉(zhuǎn)換。

使用分布類型和引擎,生成0到9之間均勻分布的隨機(jī)數(shù)

    default_random_engine dre;
    uniform_int_distribution<unsigned> uidu(0, 9);
    for (int i = 0; i < 10; ++i)
        cout << uidu(dre) << endl;

上面的uniform_int_distribution<unsigned>是均勻分布,生成0到9之間的隨機(jī)數(shù),將default_random_engine 傳遞給uidu,便可以生成均勻分布在0到9之間的隨機(jī)數(shù),一般我們將隨機(jī)數(shù)發(fā)生器的時(shí)候,是指分布和引擎。

隨機(jī)數(shù)引擎有一個(gè)序列不變的特性,在調(diào)試的時(shí)候非常有用,但是要是不注意的話代碼的結(jié)果便會(huì)出錯(cuò)。看下面的例子:

vector<unsigned> bad_randvec()
{
    default_random_engine dre;
    uniform_int_distribution<unsigned> uidu(0,9);
    vector<unsigned> ret;
    for (size_t i = 0; i < 10; ++i)
        ret.push_back(uidu(dre));
    return ret;
}

上面的代碼看起來是返回一個(gè)10個(gè)隨機(jī)數(shù)的vector,但是實(shí)際上在每次調(diào)用的時(shí)候,返回值都是一樣的。正確寫法應(yīng)該是將分布和引擎設(shè)置為static。

vector<unsigned> bad_randvec()
{
    static default_random_engine dre;
    static uniform_int_distribution<unsigned> uidu(0,9);
    vector<unsigned> ret;
    for (size_t i = 0; i < 10; ++i)
        ret.push_back(uidu(dre));
    return ret;
}

這樣每次輸出的結(jié)果便是隨機(jī)的了。

設(shè)置隨機(jī)數(shù)發(fā)生器的種子

    default_random_engine dre1(123);
    default_random_engine dre2;
    dre2.seed(time(0));
    for (int i = 0; i < 10; ++i)
        cout << dre1() << ' ';
    cout << endl;
    for (int i = 0; i < 10; ++i)
        cout << dre2() << ' ';
    cout << endl;

其中dre1使用123作為隨機(jī)數(shù)種子,dre2使用默認(rèn)的隨機(jī)數(shù)種子,而dre2.seed(time(0))是使用時(shí)間為隨機(jī)數(shù)種子,使得隨機(jī)數(shù)種子不是固定的。

生成隨機(jī)實(shí)數(shù)

很多時(shí)候我們需要生成0到1之間的隨機(jī)浮點(diǎn)數(shù),我們可以使用生成實(shí)數(shù)的分布。

    default_random_engine dre3;
    uniform_real_distribution<double> urdd(0, 1); //<>中可以是空,即使用默認(rèn)模板參數(shù),默認(rèn)為double
    for (int i = 0; i < 10; ++i)
        cout << urdd(dre3) << ' ';
    cout << endl;

分布類型d的常用函數(shù)還有以下幾個(gè):

d.min();  //返回d(e)能生成的最小值
d.max(); //返回d(e)能生成的最大值
d.reset();  //重建d的狀態(tài),使得隨后對(duì)d的使用不依賴于d已經(jīng)生成的值

生成非均勻分布的隨機(jī)數(shù)

除了均勻分布之外,我們往往還需要用到一些非均勻分布的隨機(jī)數(shù),如正態(tài)分布。

    default_random_engine dre4;
    normal_distribution<> nd(4, 1.5);//均值為4,標(biāo)準(zhǔn)差為1.5
    vector<unsigned> vals(9);
    for (size_t i = 0; i < 200; ++i)
    {
        unsigned val = lround(nd(dre4));
        if (val < vals.size())
            ++vals[val];
    }
    for (auto e : vals)
    {
        cout << string(e, '*') << endl;
    }

程序輸出如下:

***
***********
******************
********************************************
*******************************************************
********************************
******************************
*****
*

可以看到輸出的結(jié)果是大致符合正態(tài)分布,但是并不是完全對(duì)稱的,如果是完全對(duì)稱反倒證明這個(gè)隨機(jī)數(shù)生成器的性能應(yīng)該不好。

伯努利分布

隨機(jī)數(shù)中還支持生成伯努利分布的隨機(jī)數(shù)。聲明和調(diào)用的形式與前述的分布和引擎相似。

    default_random_engine e;
    bernoulli_distribution b1;  //默認(rèn)是50 / 50 的機(jī)會(huì),
        /*TODO*/

伯努利分布還可以調(diào)整概率:

    default_random_engine e;
    bernoulli_distribution b2(.60);  //概率為60 / 40 的機(jī)會(huì),
        /*TODO*/

總結(jié)

C++11新標(biāo)準(zhǔn)中的定義的隨機(jī)數(shù)的分布有20種,本文只是介紹了比較常用的幾種,新標(biāo)準(zhǔn)引入的不同分布的隨機(jī)數(shù),為程序的編寫帶來了更多的方便,可以舍棄原有C的rand函數(shù)了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容