2012-05-06 88 views
1
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

int main(int argc, char** argv) { 


    srand(time(NULL)); 
    int r = rand(); 

    printf("%d\n", r); 

    return (EXIT_SUCCESS); 
} 

當我在幾秒鐘的空間反覆運行該代碼片段,我得到越來越系列214193875號,如213252683,213975384,中,214445980.看樣子對我來說就像我只是打印出系統時間一樣 - 當我添加printf("%d\n", time(NULL))行時,似乎證實了這一假設;到代碼。我究竟做錯了什麼?我在Mac OS X 10.6.1(雪豹)上運行,但我只使用標準庫函數,所以它不應該有所作爲。謝謝!簡單的隨機數生成器不工作

+0

看看第二個電話到蘭特()返回。另外,請參閱http://linux.die.net/man/3/rand,因爲它討論了僞隨機數生成器的示例實現。 – Chris

+0

僞隨機數發生器的基本規則:種子一次,產生很多次。如果您繼續重新播種它不起作用。 –

+0

@Chris:根據需要,第二次調用rand()似乎正在生成PSRN。我非常驚訝第一個電話的行爲! – Gautam

回答

3

僞隨機數被生成爲從初始種子派生的混沌序列。 srand通過設置此種子來初始化隨機性。顯然,序列中的第一個隨機數是種子本身 - 這是您設置的time()值。

這是什麼原因,爲什麼生成一個隨機序列正確的方法是在程序的開始調用srand()只有一次,然後只調用rand()(好吧,也許直到序列開始循環,這不應該發生得太快,但這取決於生成函數)。正如你所看到的,調用srand()通常會使隨機性惡化。

+1

我會說這是一個非常破碎的'rand'實現,它將種子本身作爲第一個值返回。當然OP的代碼也被破壞了;如果你多次使用相同的種子,當然你會得到相同的輸出。但是,使用相鄰的種子肯定不應*給出相鄰的輸出。 –

0

當我在幾秒鐘的空間反覆運行這個代碼片斷, 我得到越來越一系列 214193875號,如213252683,213975384,中,214445980.

我不能重現此。在我的系統(Debian Linux)上,我得到了沒有排序的數字。此外,結果與您在打印time(NULL)時得到的結果不同。

這是因爲它應該是:你播種隨機數發生器與當前時間(以秒爲單位)。因此,只要時間(下至秒)相同,您的程序將打印相同的結果。

我在做什麼錯?

那麼,這取決於你想要什麼。如果每次運行都需要隨機數,則需要更好的隨機性來源。你可以嘗試像gettimeofday這樣的功能,它具有更高的分辨率(通常是毫秒,我相信)。另外,混入其他隨機來源,例如您的流程的ID。

在大多數程序中,您看到的效果沒有問題,因爲通常只在起始處調用srand(),然後rand()在每次調用時返回不同的數字。

如果你想要「安全」(即不可預知)的隨機數,那就是整個其他遊戲。見例如Wikipedia的概述。

0

隨機數發生器差別很大,所以這將很難在其他機器上重現。它看起來像你的實現中的第一個數字就是種子值。例如,我的第一個數字似乎與種子呈線性關係。通常情況下,您將在程序中撥打srand一次,並且rand多次,並且連續呼叫將獲得更多隨機結果。如果你想避免這個問題,這將是合理的做法:

srand(time(NULL)); 
rand(); 
int r = rand(); 

printf("%d\n", r); 

第一rand呼叫確保種子沒有得到恢復,而下一個應該拿起出現更隨機的東西。請注意,如果您在足夠短的時間內運行程序兩次(例如time(NULL)在兩次運行中都是相同的),則會得到完全相同的結果。這絕對是值得期待的 - 如果這是一個問題,使用不同的種子值(pid + time可能是一個好的開始,或者更高的分辨率時間)。

1

萬一它有助於我一般都用這種方式:

int rand_between(int min, int max) 
{ 
    static int flag = 1; 
    FILE *urandom; 
    unsigned int seed; 

    if (flag) 
    { 
     flag = 0; 
     if (!(urandom = fopen ("/dev/urandom", "r"))) 
     fprintf(stderr, "Cannot open /dev/urandom!\n"); 
     fread(&seed, sizeof(seed), 1, urandom); 
     srand(seed); 
    } 
    return ((int)rand() % (max - min)) + min; 
} 

要獲得一個隨機的大寫字母:

char letter = (char)rand_between('A', 'Z'); 
0

您應該使用隨機()代替蘭特()。它在各方面都優於rand(),並且它也包含在stdlib中。
試試下面的代碼:

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char** argv) { 
int r = random(); 
printf("%d\n", r); 
return (EXIT_SUCCESS); 
}