2016-06-11 82 views
0

我的問題很簡單(也許很傻)。 我需要一個使用C語言的儘可能簡單的長隨機數。我通過互聯網進行了研究,並沒有找到任何可以幫助我的東西。我唯一能找到的是rand()函數不能處理大於32,767的數字。C中的長隨機數

這裏是我的代碼部分,長數應介於0和1000000:

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

#define MAX 999999 

void main() 
{ 
    int i; 

    printf("\n Just a test with random numbers."); 

    printf("\n ------------------------------------\n\n"); 

    srand(time(NULL)); 

    for(i = 0; i < 50; i++) 
    { 
     printf(" %li\n", rand() % MAX+1); 
    } 

    printf("\n ====================================\n"); 
    getch(); 
} 

回答

-1

壞,但工作的解決辦法是用MAX/RAND_MAX(我乘蘭特(的結果)相信這是不變的,如果不是的話,32767)。

我仍然認爲應該有一個蘭特較大的數字在那裏,雖然。

EDIT:需要強制轉換的分割漂浮(或雙),然後再返回到長。

3

您可以通過或建立更大的數字:荷蘭國際集團一起多次打電話給蘭特()。

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

#define LIMIT (1000000) 

static uint16_t highest_bit(uint64_t v) { 
    uint16_t out = 0; 
    while (v > 0) { 
     v >>= 1; 
     ++out; 
    } 
    return out; 
} 

uint32_t myrand() { 
    static bool init = 0; 
    static uint16_t n; 
    static uint16_t shift; 
    if (!init) { 
     uint16_t randbits = highest_bit(RAND_MAX + (uint64_t)1L); 
     uint16_t outbits = highest_bit(LIMIT); 
     n = (outbits + randbits - 1)/randbits; 
     shift = randbits; 
     init = 1; 
    } 
    uint32_t out = 0; 
    for (uint16_t i=0; i<n; ++i) { 
     out |= rand() << (i*shift); 
    } 
    return out % LIMIT; 
} 

應當指出的是,這種方法會有偏差(即所有的數字將不會有相同的概率),它是絕對不是加密安全。如果你想要的話,你根本不應該使用rand()

下面就來測試所有的數字都至少可能得到一點主要功能:

int main() { 
    bool* seen = calloc(LIMIT, sizeof(bool)); 
    if (!seen) { 
     fprintf(stderr, "failed to malloc 'seen' array\n"); 
     return 1; 
    } 
    uint32_t nseen = 0; 
    uint32_t ntries = 0; 
    // this could take a long time -- you can use Ctrl-C to abort a command-line program 
    while (nseen < LIMIT) { 
     if ((ntries & 0xffff) == 0) { 
      printf("after %u tries, we've seen %u different numbers.\n", ntries, nseen); 
     } 
     ++ntries; 
     uint32_t r = myrand(); 
     if (!seen[r]) { 
      seen[r] = true; 
      ++nseen; 
     } 
    } 
    printf("Found them all after %u tries!\n", ntries); 
    return 0; 
} 
1

我假設你想在區間[0的隨機數,百萬[即在一個範圍內10的長度。

它是完全一樣的在範圍[0,1000,一個用於高階(十進制)數字,一個用於低次採摘者兩個隨機數。但是,這是很容易在這個範圍內的工作......

如果你想有一個正確的隨機生成,你應該擔心的每一個可能的數的概率,並儘量保持它儘可能平等。因此,您必須首先搜索RAND_MAX以下1000的最大功率,拒絕大於它的所有數字,並取每個保留值的模數1000。

// Find the max number to keep 
int period = 1000 
unsigned int max = period; 
while (max < (unsigned long) RAND_MAX) { 
    unsigned long t = max * period; 
    if (t < max) break; // test for a possible overflow 
    max = t; 
} 

然後可以使用

for(;;) { 
    unsigned long randnum = rand(); 
    if (randnum < max) { 
     randnum %= period; 
     break; 
    } 
} 

而當你在區間[0,1000兩個隨機數[,說n1n2,只是做:

n = period * n1 + n2; 

當然上面假設你有一個正確的rand函數。如果不能確定使用random - 我的系統上rand手冊頁指出它使用相同algorythm爲random這就是爲什麼我認爲我可以安全地使用它,但它也說:

然而,在老蘭特()實現,並在目前在不同系統上的實現方式,低階比特比隨高階比特要少得多。當需要良好的隨機性時,不要在可移植的應用程序中使用此函數。 (使用隨機(3)代替)。

+0

'max'應該可能是'unsigned long',應該不是嗎? – Kundor