2006年3月17日 星期五

用 C 呼叫 rand() 每次都回傳相同結果?

Standard

為了寫一個隨機產生 ID 的程式,我用C去呼叫 rand() 這亂數產生函式,然而經過測試後發現,每次程式執行所產生的亂數都是一樣的。這問題讓我花了點時間研究了一下,我發現並非每次執行都一樣,而是每秒內產生 出來的亂數是一樣的。很明顯的,這裡的亂數種子設定出了點問題。

在過去習慣上,在使用亂數前 我們會用 srand(time(0)) 設定亂數種子,而一般的書籍也是這樣教我們。但這種方式設定亂數種子,種子的變化是以秒為單位,也就是每秒只變動一次。由於種子在一秒鐘之內都是一樣的, 每次使用 rand() 時,產生出來的亂數也都會是相同的。


這樣設定亂數種子其實 並沒有錯,因為一般程式只需要在開頭設定第一次,之後就不必再設。但如果我們要寫的是一個指令,使用者就可能在一秒鐘之內重覆執行你的程式很多遍。那將會 導致亂數種子被重新定義很多遍。每當種子被重新設定,rand()自然就會把亂數表重頭讀取,當然,每次所得到的亂數就會相同。


我暫時想出了個解決辦法,就是針對種子再給予時間以外的變數,讓每次執行的種子變得更不一樣。於是我將種子設定改成這樣:

srand(time(0)+getpid());


這 以程式執行時的行程處理ID加了進來當種子,因為每個程式的 PID 一定不一樣,如果要一樣也要等許多的程式執行後,重頭分配 PID 才有可能相同。以 PID 再加上原本每秒產生出來的時間,如此產生出來的種子必定獨一無二。這點小技巧能夠解決 rand() 每次回傳都相同的問題。

註:本文是架構在 Linux 上,並以 gcc 編譯所產生的程式當基準,若在 Windows 等其他平台和以 VC++ 、Turbo C等其他款編譯器,不能保證本文所談到的東西能起任何作用。