2012-02-27 62 views
22

每次我運行一個程序rand()它給了我相同的結果。爲什麼rand()在每次運行中產生相同的數字序列?

實施例:

#include <iostream> 
#include <cstdlib> 

using namespace std; 

int random (int low, int high) { 
    if (low > high) return high; 
    return low + (rand() % (high - low + 1)); 
} 
int main (int argc, char* argv []) { 
    for (int i = 0; i < 5; i++) cout << random (2, 5) << endl; 
} 

輸出:

3 
5 
4 
2 
3 

每次我運行它輸出每次相同的數字程序。有沒有解決的辦法?

回答

33

未設置隨機數發生器的種子。

如果調用函數srand(時間(NULL)),那麼你會得到更多的隨機結果:

的原因是,從rand()函數產生的隨機數實際上不是隨機的。它只是一個轉變。維基百科更好地解釋了僞隨機數發生器的含義:確定性隨機位發生器。每次調用rand()時,都會生成種子和/或最後一個隨機數(C標準沒有指定使用的算法,儘管C++ 11有指定一些常用算法的功能),運行對這些數字進行數學運算,並返回結果。所以如果種子狀態每次都是相同的(就像你不用真正的隨機數字調用srand一樣),那麼你總是會得到相同的「隨機」數字。

如果您想了解更多,您可以閱讀以下內容:

http://www.dreamincode.net/forums/topic/24225-random-number-generation-102/

http://www.dreamincode.net/forums/topic/29294-making-pseudo-random-number-generators-more-random/

1

您需要爲隨機數生成器生成種子(參見函數'srand')。假設你沒有做密碼學,那麼用'時間'的輸出進行播種可能就足夠了。

11

如果您在未先致電srand()的情況下致電rand(),它將會如同隱式調用srand(1)那樣操作。標準C99 7.20.2.2 The srand function(其上cstdlib基於)的相關位指出:

如果蘭特被稱爲已作出函數srand任何呼叫之前,相同的序列應爲srand時先用種子稱爲生成1.

值換句話說,你得到相同的序列中的每個時間。你可以改變你main到:

int main (int argc, char* argv []) { 
    srand (time (0)); // needs ctime header. 
    for (int i = 0; i < 5; i++) 
     cout << random (2, 5) << endl; 
    wait(); 
} 

來解決這個問題,假設你不運行它不止一次第二。

如上所述,您需要使用ctime標題。你也應該拉cstdlib因爲這是randsrand住的地方。使用cXXX標題而不是XXX.h標題(例如cmath而不是math.h)通常也是一個好主意。

所以,在作出所有這些變化(與使用顯式的命名空間,這是我比較喜歡,雖然別人可能沒有),我結了:

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

void wait() { 
    int e; 
    std::cin >> e; 
} 

int random (int low, int high) { 
    if (low > high) return high; 
    return low + (std::rand() % (high - low + 1)); 
} 

int main (int argc, char* argv []) { 
    std::srand (std::time (0)); 
    for (int i = 0; i < 5; i++) 
     std::cout << random (2, 5) << '\n'; 
    wait(); 
} 

賦予不同的順序,每次我無論如何,運行它幾次。顯然,數據重複的時間有很長的限制(只有4種可能性),輸出的「隨機」特性意味着它可能在此之前重複:-)

0

實際上,僞隨機數。爲了使它們「更隨機」,您可以使用「更改」(最常見的是當前時間)的內容對隨機數生成器進行播種。

+1

Nit:數學上,這不會讓他們「更隨機」。 – 2012-02-27 10:51:11

+0

的確如此,但是在OP的問題中......(加上引號;-) – John3136 2012-02-27 23:48:41

2

這就是rand()功能的一個特點。

你有什麼不是一個隨機數發生器,但更嚴格的是一個"Pseudo Random Number Generator"。能夠爲同一個種子重現相同的隨機序列(使用srand(x)函數種子)對於在程序運行中重現錯誤或保持狀態非常重要。

個人而言,我使用此功能可以在基於地形渲染器的monte carlo中暫停/保留渲染過程。一個好的副作用是你可以在不同的機器上保證不同的蒙特卡洛試驗,因此能夠產生有保證的不同結果,然後可以在最後一步中減少到更高質量的最終結果(當然,你以後可以重複使用這種更高質量的最終結果可以產生更高質量的結果)。

但是請注意,C和C++都沒有定義從rand()開始的數字序列。因此,如果您需要跨平臺的保證序列,請使用C++ 11的新隨機數生成器之一(例如,mersenne twister),自行推出(但某些生成器幾乎無法掌握,因爲它們中的大多數依賴於特定的溢出行爲實現可能不是微不足道的),或者使用第三方組件(例如boost :: random)。

1

use randomize()。它會自動給這個值分類。 或者如果你想使用rand(),那麼你可以通過使用srand(seedvalue)來播種它;種子價值可以是任何類似系統時間..每次會給你不同的隨機數

+1

'randomize'不是一個標準的C++函數。你在說哪個平臺? – 2015-02-01 09:33:58

相關問題