2016-01-30 23 views
-1

我是C++學生,我正在創建一個隨機數生成器。如何在C++中改進這個隨機數生成器代碼?

Infact我應該說我的算法選擇一個定義範圍內的數字。

我寫這個只是因爲我的好奇心。

我不挑戰現有的圖書館功能。

我在編寫基於隨機性的應用程序時總是使用庫函數,但我再次聲明,我只是想因爲我的好奇心而使它成爲現實。

我也想知道我的算法或我的方法是否有問題。 因爲我GOOGLE了一下PRNG是如何工作的,在一些網站上他們說有一個數學算法,並且預定義的一系列數字和一個種子只是將指針設置在系列中的不同點,並且在一段時間之後,序列重複自身。

我的算法剛開始在可能值的數組中移動來回,種子每次都會用不同的值打斷循環。我不這樣做是錯誤的。我得到的答案提示了不同的算法,但他們沒有解釋我目前的算法有什麼問題?

是的,有一個與我的種子有問題,因爲它是不準確和取得的成績有點預見如下: -

COUT < < RN(50,100);

運行四次的結果是74,93,56,79。

查看「遞增順序」的模式。

而對於大範圍模式可以很容易地看到。我得到了一個好的種子的答案,但也推薦了一個新的算法(但沒有說明爲什麼?)。

另一種方法可能是隨機隨機產生一個新序列,並且增加順序的模式將關閉。對重新排列的任何幫助也將是好的。下面是代碼。如果我的功能是不可能的,請通知我。

感謝您的期待。

int rn(int lowerlt, int upperlt) 
{ 
    /* Over short ranges, results are satisfactory. 
    * I want to make it effective for big ranges. 
    */ 

    const int size = upperlt - lowerlt; // Constant size of the integer array. 

    int ar[size]; // Array to store all possible values within defined range. 
    int i, x, ret; // Variables to control loops and return value. 
    long pointer = 0; //pointer variable. The one which breaks the main loop. 


    // Loop to initialize the array with possible values.. 
    for (i=0, x=lowerlt; x <= upperlt; i++, x++) 
     ar[i]=x; 

    long seed = time(0); 

    //Main loop . To find the random number. 
    for (i=0; pointer <= seed; i++, pointer++) 
    { 
     ret = ar[i]; 
     if (i == size-1) 
     { 
      // Reverse loop. 
      for (; i >= 0; i--) 
      { 
       ret=ar[i]; 
      } 
     } 
    } 

    return ret; 
} 
+3

的「主要問題」是寫的RNG是硬的,並沒有什麼特別,建議你採用的方法。對這個問題的回答只會包含另一種現有的算法,您可以自己找到另外一種算法,以獲得更多好處。 – EJP

+0

@EJP建築RNGs很難或沒有,找到解決方案很重要。我知道庫函數。我只是要求一點幫助。我只是想知道不同的編程技術。我剛來這地方。 – anjanik012

+0

所以去找一個,如我所建議的。而不是從猜測開始。你會學到很多。 – EJP

回答

0

警告:從您的文章,除了你的隨機數生成算法,你的問題一個是獲得良好的種子值,所以我會解決它的一部分。

您可以使用/dev/random來獲得種子值。這將是一個開始的好地方[而且它本身就足夠了],但從某些角度來看可能被認爲是「作弊」。

所以,這裏是「熵」的一些其他來源:

使用天時鐘源的更高分辨率時間:gettimeofdayclock_gettime(CLOCK_REALTIME,...)稱之爲「CUR_TIME」。分別只使用微秒或納秒部分,稱之爲「cur_nano」。請注意,cur_nano通常本身非常隨機。

做一個getpid(2)。這有幾個不可預知的位,因爲在調用之間其他程序開始,我們不知道有多少。

創建一個新的臨時文件並獲取該文件的inode號碼[然後刪除它]。這隨着時間的推移緩慢變化每次調用時可能都相同[或不]

系統啓動時獲取系統時鐘的高分辨率值,稱之爲「sysboot」。

獲取「會話」開始時間的高分辨率值:當程序的父shell啓動時,將其稱爲「shell_start」。

如果您使用的是Linux,那麼您可以計算一個校驗和/proc/interrupts,因爲它一直在變化。對於其他系統,獲取各種類型中斷的數量的散列[應該可以從某種類型的系統調用中獲得]。

現在,創建上述所有(例如)的一些散列:

dev_random * cur_nano * (cur_time - sysboot) * (cur_time - shell_start) * 
getpid * inode_number * interrupt_count 

這是一個簡單的等式。您可以使用一些XOR和/或sum操作來增強它。試驗,直到你找到一個適合你的東西。

注意:這隻會給你PRNG的種子值。你必須創建一個從別的東西你PRNG(如伯爵的線性算法)

0
unsigned int Random::next() { 
    s = (1664525 * s + 1013904223); 
    return s; 
} 

「S」與該函數的每一個電話越來越多。 正確的是

unsigned int Random::next() { 
    s = (1664525 * s + 1013904223) % xxxxxx; 
    return s; 
} 

可能使用此功能

long long Factor = 279470273LL, Divisor = 4294967291LL; 
long long seed; 
next() 
{ 
    seed = (seed * Factor) % Divisor; 
}