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紀元的開始,也有需要注意的三個重要的事情:
- 你產生將序列只有在兩次調用之間至少經過了一秒時纔會有所不同。
- 根據實際實施情況,如果用於種子
rand
的時間點彼此接近(與自Epoch以來的時間相比),則結果序列可能開始具有類似性。 Afaik,這是MSVC實施中的情況。如果這是有問題的,只需丟棄序列的前幾百或上千個值即可。(正如我現在所知道的,這對於rand
常用的差RNG並沒有多大幫助,所以如果有問題,請使用<random>
,如下所述)。
- 您的號碼最後並不是很隨意:如果有人知道您何時致電
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是一款有趣的手錶。
查看'srand'和'rand'的文檔。在C++ 11或更高版本中,應該使用http://en.cppreference.com/w/cpp/numeric/random中的類型。 – Kevin
如果你看[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」。 –
P.S.我不同意這應該作爲一個副本來關閉,因爲它更多地討論'時間'和'srand'之間的相互作用,而不是rand/srand本身。 –