C++ 利用 標頭檔案 , 產生一個random number generator

JUAN425發表於2014-08-13

標頭檔案<cstdlib>中有一個重要的函式 rand() , 可以作為隨機數發生器。

現在現在我想產生一個隨機數, 我使用如下的程式:

#include <iostream>
#include <cstdlib>

using namespace std;


int main()
{
    cout << rand() << endl;
    return 0;
}

問題來了, 雖然我們產生了一個隨機數, 但是無論我執行上述程式多少遍(重新編譯, 在執行,也一樣是41), 都產生一個確定的數。 即41, 如下:



這是為什麼呢。

答案是要想得到一個隨機數, 我們需要給這個隨機數發生器(random number generator) 輸入一個seed(種子)。



現在讓我們在函式中呼叫rand() 函式25次, 用於產生25個隨機數:



上述的情況也是一樣的, 無論是將該程式執行多少遍, 或者再次編譯, 執行, 結果仍然是產生了25個與上述隨機數完全一樣的隨機數。 這仍然是沒有seed的原因。


在舉一個例子, 模擬骰子。 隨機出現的資料是: 1, 2, 3, 4, 5, 6,  現在我們程式設計產生這個範圍的數字, 投25次, 程式如下:

#include <iostream>
#include <random>


using namespace std;

int main()
{
    for (int i = 0; i < 25; i++) {
        cout << 1+ (rand() % 6) << endl; // 必須加1, 否則產生0
    }
    return 0;
}



執行結果如下:



不難推廣, 我們可以產生任意範圍整數的隨機數。

但是問題來了, 由於上述的幾個程式的隨機數沒有seed, 所有無論我們執行多少次程式, 產生的隨機數都是相同的。

問什麼呢?

 因為沒有計算機能夠產生完全隨機的隨機數。  計算機畢竟不是人, 計算機必須按照一定的演算法(Algorithm), 一定的指令去執行命令。 也就是說計算機不可能產生完全隨機的資料。 但是計算機通過一定的複雜的演算法, 我們可以使得其產生的資料看起來是隨機的。  

C++產生隨機數可以使用的seed random number。 常用的函式是srand()(函式有一個引數, 使我們給進去的任何一個隨機數),:

 

#include <iostream>
#include <cstdlib>



using namespace std;

int main()
{
    srand(6);
    for (int i = 0; i < 25; i++) {
        cout << 1+ (rand() % 6) << endl;
    }
    return 0;
}

產生的結果如下:



顯然不同了。 但是如果我們不改變srand(6)函式中的引數, 只要我們執行, 或者重新編譯執行, 仍然出現同樣的結果(同上面的問題一樣)。 但是隻要我們改變srand() 中的引數, 重新編譯, 執行, 出現不同的結果。 例如我們將srand(6)改為srand(10), 就會改變的:




現在我們給出上述所有問題的終極解決辦法:

這個解決辦法需要包含一個叫做<ctime>的標頭檔案。 這個標頭檔案允許我們去得到計算機的時鐘。 如下:

#include <iostream>
#include <cstdlib>
#include <ctime>


using namespace std;

int main()
{
    srand(time(0)); 
    for (int i = 0; i < 25; i++) {
        cout << 1+ (rand() % 6) << endl;
    }
    return 0;
}

編譯執行:



再次執行:



也就是說只要重新執行, 就會重新產生和偽隨機數。 這正是我們希望得到的結果。 


現在我們解釋原因:

我們知道可以通過srand() 去修改我們的演算法。 但是如果我們向srand()中傳遞一個確定的數字, 那麼演算法產生的結果也是一個確定的數字。 無論我們執行多少次,結果都是一樣的。 

但是我們想srand 傳遞的引數為time(0), time(0) 函式的返回值每一秒都在變化。  隨機這樣 , 每一次我們執行函式的時候 , 結果都看似隨機的了。


相關文章