2016-05-12 51 views
0

我最近一直在學習如何從一本初學者書籍編寫C++遊戲,並且我得到了一個教訓,在那裏我必須製作一個遊戲,在那裏我必須猜測計算機的隨機挑選號碼,我必須使用此行代碼:rand()和srand()在C++中的函數

srand(static_cast<unsigned int>(time(0))); 
variable=rand(); 

我明明使用的iostream cstdlib和ctime.I並不真正瞭解這個works.How怎麼回事採摘時間和日期,以及通過什麼規則是它轉換成一個unsigned int。基本上,這些功能是如何工作的。 謝謝!

+3

查看'srand'和'rand'的文檔。在C++ 11或更高版本中,應該使用http://en.cppreference.com/w/cpp/numeric/random中的類型。 – Kevin

+0

如果你看[time()']的規範(http://en.cppreference.com/w/cpp/chrono/c/time),你會發現它返回一個'time_t'。如果你看看[time_t'的定義](http://en.cppreference.com/w/cpp/chrono/c/time_t),你會發現它幾乎總是一個整型。事實上,我不知道它沒有的實現。因此沒有問題將其轉換爲常規的「int」。 –

+1

P.S.我不同意這應該作爲一個副本來關閉,因爲它更多地討論'時間'和'srand'之間的相互作用,而不是rand/srand本身。 –

回答

7

1.關於time()

time(或更好std::time在C++)是返回表示以某種方式在當前時間某個整數或浮點數的函數。

它沒有指定它實際返回的算術類型以及它如何表示當前時間,但是,最常見的情況是,您將獲得一些整數類型,它保存自Unix時代開始以來的秒數。

2.關於srand()

srand是使用它的參數(這是unsigned int類型的),即所謂的種子,以設置僞隨機數發生器rand的內部狀態的功能。當我在這個答案的其餘部分中寫隨機,請閱讀僞隨機

使用不同的種子通常會導致隨後調用rand產生的隨機數的不同序列,而再次使用相同的種子將導致完全相同的隨機數序列。

3.使用time()種子rand()

如果我們不希望我們每次運行程序時得到相同的隨機數,我們需要一些種子是在每次運行時不同。當前時間是這種種子廣泛使用的來源,因爲它不斷變化。

表示當前時間的此整數(或返回的任何其他time)現在轉換爲unsigned int,其中static_cast。由於所有算術類型都隱含地轉換爲unsigned int,但這種明確的轉換並不是實際需要的,但演員可能會默認一些警告。隨着時間的推移,我們可以預期產生的unsigned int以及由rand產生的隨機數序列改變。

4.陷阱

如果像常見,time返回的秒數,因爲Unix紀元的開始,也有需要注意的三個重要的事情:

  1. 你產生將序列只有在兩次調用之間至少經過了一秒時纔會有所不同。
  2. 根據實際實施情況,如果用於種子rand的時間點彼此接近(與自Epoch以來的時間相比),則結果序列可能開始具有類似性。 Afaik,這是MSVC實施中的情況。如果這是有問題的,只需丟棄序列的前幾百或上千個值即可。(正如我現在所知道的,這對於rand常用的差RNG並沒有多大幫助,所以如果有問題,請使用<random>,如下所述)。
  3. 您的號碼最後並不是很隨意:如果有人知道您何時致電srand,他可以從中得出整個隨機數序列。這實際上導致了一個使用srand(time(0))生成其「隨機」加密密鑰的勒索軟件的解密工具。

另外,由rand產生的序列傾向於具有差的統計特性,即使種子是好的。對於像你這樣的玩具程序,這可能很好,但是,對於真實世界的使用,應該意識到這一點。

5.新<random>

C++ 11引入了新的隨機數的設施,是優於老rand基礎的東西很多方面。他們在標準標題<random>中提供。它包括std::random_device,它提供了一種方法來獲得實際上隨機的種子,強大的僞隨機數發生器,如std::mt19937以及將產生的隨機序列映射到整數或浮點範圍而不會引入不必要的偏倚的工具。

下面是一個例子如何隨機地滾動在C++ 11的模頭:

#include <random> 
#include <iostream> 

int main() 
{ 
    std::random_device rd; 
    std::mt19937 gen(rd()); 
    std::uniform_int_distribution<> dis(1, 6); 

    for (int n=0; n<10; ++n) 
     std::cout << dis(gen) << ' '; 
    std::cout << '\n'; 
} 

(代碼從cppr注:std::random_device不與MinGW的正常工作,至少在版本( Nuwen MinGW5.3)我測試過了!

還應該注意的是,mt19937的狀態空間遠大於我們(通常)從單個調用random_device中跳出的32位。再次,這對玩具程序和家庭作業來說很可能並不重要,但作爲參考:Here是我嘗試正確地播種整個狀態空間,並在答案中加上一些有用的建議。

如果您有興趣瞭解關於rand的更多詳情和<random>this是一款有趣的手錶。

0

第一行: srand()是一個僞隨機數發生器。在你的情況下,它是用系統上的當前時間(執行時間)初始化的。 第二行: 配置僞隨機數發生器後,可以通過調用rand()來檢索隨機數。