2013-10-02 44 views
2

林這樣的功能:生成簡單的隨機數與時間在C

int rand2(int lim) 
{ 
     static long a = 1; // could be made the seed value 
     a = (a * 32719 + 3) % 32749; 
     return ((a % lim) + 1); 
} 

獲得隨機數的堆棧,它做工精細,但每次我啓動此功能時,我將有許多相同的堆棧,所以我想使用的時間()系統函數每次有不同的堆棧

int rand3(int lim, int dat_time) 
{ 
    static int a = dat_time; // could be made the seed value              
    a = (a * 32719 + 3) % 32749; 
    return ((a % lim) + 1); 
} 

後來我給我的電腦的一個時間的時間(),因爲變量是靜態

int    main() 
{ 
    int   rd; 
    time_t  timee; 
    int   seed; 

    timee = 0; 
    timee = time(timee); 
    seed = timee; 
    while(42) 
    { 
     rd = rand3(52, seed); 
     printf("%d\n", rd); 
     getchar(); 
    } 
} 

然後我得到一個錯誤說dat_time不是恆定的,但因爲我用它一個時間,我不知道爲什麼

+4

一個類似的問題[爲什麼編譯器限制全局變量總是被常量值初始化?](http://stackoverflow.com/questions/19130321/why-compiler-restricts-global-variable-always-to-be-初始化的常量值) – 2013-10-02 09:01:48

+0

我知道沒有允許此代碼的C編譯器。你甚至試圖編譯它?如果是這樣,你需要一個新的編譯器。 – Lundin

回答

3

靜態存儲持續時間的變量被初始化。

這意味着不能使用直到運行時才能確定的變量來初始化它們。如果您刪除了static,那麼錯誤將會消失,但是您每次調用它時都會重新生成隨機數生成器。

你真的應該初始化隨機種子一次要求第一隨機數(如srand()/rand()從C標準庫)之前,然後通過序列中的值,用你的隨機函數週期。這可能喜歡的東西來完成:

int rand4 (int numLimit) { 
    static int randSeed, needsInit = 1; 
    if (needsInit) {      // This bit only done once. 
     randSeed = time(0); 
     needsInit = 0; 
    } 
    randSeed = (randSeed * 32719 + 3) % 32749; 
    return (randSeed % numLimit) + 1; 
} 

A的srand()/rand()typical implementation是沿着線:

// RAND_MAX assumed to be 32767. 
static unsigned long int next = 1; 
void srand(unsigned int seed) { next = seed; } 
int rand(void) { 
    next = next * 1103515245 + 12345; 
    return (unsigned int)(next/65536) % 32768; 
} 

其自己的源文件,以便next種子是從視圖中隱藏。這符合預期的行爲,撥打rand()而不先撥打srand()與您撥打srand (1)時的行爲相同。


,並根據您的評論,你需要一定數量的呼叫生成所有號碼從1到52,這聽起來像你正在使用這生成卡片隨機甲板。如果是這樣的話,還有更好的辦法,比生成一個隨機數字並扔掉那些你已經看到的。

隨着剩餘甲板的尺寸越來越小,該解決方案迅速惡化。對於O(1)時間和空間解決方案,請使用Fisher-Yates shuffle。

的基本算法是使用一個未排序的列表,並且簡單地交換的最終元件與一個隨機選擇的一個,該列表縮減尺寸由一個:

dim n[N]     // gives n[0] through n[N-1] 

for each i in 0..N-1:  // initialise them to their indexes 
    n[i] = i    // (use i+1 for 1-10 instead of 0-9). 

nsize = N     // starting pool size 
do N times: 
    i = rnd(nsize)  // give a number between 0 and nsize-1 
    print n[i] 
    nsize = nsize - 1  // these two lines effectively remove the used number 
    n[i] = n[nsize] 

由產生的是數字:

<------ n[] ------> 
0 1 2 3 4 5 6 7 8 9 nsize rnd(nsize) output 
------------------- ----- ---------- ------ 
0 1 2 3 4 5 6 7 8 9  10   4  4 
0 1 2 3 9 5 6 7 8  9   7  7 
0 1 2 3 9 5 6 8   8   2  2 
0 1 8 3 9 5 6   7   6  6 
0 1 8 3 9 5    6   0  0 
5 1 8 3 9    5   2  8 
5 1 9 3     4   1  1 
5 3 9     3   0  5 
9 3      2   1  3 
9      1   0  9 
+0

似乎工作,我做更多的測試。 – Saxtheowl

+0

好吧,看起來不錯,而且我需要<300電話才能獲得52個不同的隨機數,我需要> 50000000在我以前的所有52的測試之前^^ – Saxtheowl

+0

感謝您的鏈接,我會留在我以前因爲資源需求很少 – Saxtheowl

0

從int A = dat_time消除靜電,並使用來自隨機數作爲種子返回爲下一個。任何代碼開始運行並且它們必須與在可計算一個表達式被初始化編譯時間之前

int rand3(int lim, int dat_time) 
{ 
    int a = dat_time; // could be made the seed value              
    a = (a * 32719 + 3) % 32749; 
    return ((a % lim) + 1); 
} 

int    main() 
{ 
    int   rd; 
    time_t  timee; 
    int   seed; 

    timee = 0; 
    timee = time(timee); 
    seed = timee; 
    while(42) 
    { 
     rd = rand3(52, seed); 
     printf("%d\n", rd); 
     getchar(); 
     seed = rd; // < Use the new random number as the seed for the next one 
    } 
} 
+1

是的,但是如果你使用返回值rd作爲下一次調用的種子,那麼隨機數的堆棧將每次相同 – Saxtheowl

+0

,你不會。但這不是你問的問題。 – Neil

0

如果您將種子傳遞給隨機數生成器函數,那麼您必須小心地在每次調用時更改種子,否則您將始終獲得相同的數字。

相反,我建議你重複使用標準srandrand函數使用的模式,以創建兩個函數:一個設置種子,一個獲取隨機數。種子將成爲全局變量而不是靜態變量。


當然可以使用功能單一,但隨後的函數必須能夠變化種子。這可以通過引用傳遞的「種子」 /「狀態」的說法來完成:

int rand3(int lim, int *state) 
{ 
    *state = (*state * 32719 + 3) % 32749; 
    return ((*state % lim) + 1); 
} 

然後,你必須使用運營商&的地址的調用函數時:

int rng_state = time(NULL); /* See the initial state (aka seeding) */ 

for (int i = 0; i < 10; ++i) 
    printf("A random number: %d\n", rand3(52, &rng_state)); 
-1

這應該工作中,我寫了一個::

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

int main (void) 
{ 
    int r; 

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

    printf ("random number = %d\n", r); 

    return 0; 
} 

但我建議,你可以從

刪除static關鍵字
+0

-1不回答問題。 OP想要幫助他/她自己的隨機數發生器。他們沒有要求使用標準庫的'rand()'函數。 – Caleb