2015-10-08 6 views
12

Ich brauche zufällige 64-Bit-Ganzzahlen ohne Vorzeichen mit C. Ich meine, der Bereich sollte 0 bis 18446744073709551615 sein. RAND_MAX ist 1073741823.So generieren Sie zufällige 64-Bit-Ganzzahl ohne Vorzeichen in C

Ich fand einige Lösungen in den Links, die mögliche Duplikate sein könnten, aber die Antworten verkettet meistens einige rand() Ergebnisse oder einige inkrementelle arithmetische Operationen. Die Ergebnisse sind also immer 18 oder 20 Ziffern. Ich möchte auch Ergebnisse wie 5, 11, 33387, nicht nur 3771778641802345472.

Übrigens, ich habe wirklich nicht so viel Erfahrung mit dem C, aber jeder Ansatz, Code-Beispiele und Ideen könnten von Vorteil sein.

+9

** Nicht ** concatenate 'rand()', wie Sie alle Arten von Autokorrelationseffekte haben werden, und die Verteilung wird nicht sei einheitlich. Werfen Sie einen Blick auf diese: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/c-lang.html – Bathsheba

+12

'Ich möchte auch Ergebnisse wie 5 , 11, 33387' => es gibt 10 mal mehr Zahlen zwischen 1000000000000000000 und 9999999999999999999 als zwischen 0 und 1000000000000000000 ... also erwarten Sie nicht, Zahlen wie 5 bald zu sehen –

+1

Sie scheinen verwirrt über die Basis 10 Ziffern (0. ..9) und Bits (Basis-2 Ziffern). Halte diese in deinem Denken getrennt, um es besser zu verstehen. – hyde

Antwort

-1
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <time.h> 

unsigned long long int randomize(unsigned long long int uint_64); 

int main(void) 
{ 
    srand(time(0)); 

    unsigned long long int random_number = randomize(18446744073709551615); 

    printf("%llu\n",random_number); 

    random_number = randomize(123); 

    printf("%llu\n",random_number); 

    return 0; 

} 

unsigned long long int randomize(unsigned long long int uint_64) 
{ 
    char buffer[100] , data[100] , tmp[2]; 

    //convert llu to string,store in buffer 
    sprintf(buffer, "%llu", uint_64); 

    //store buffer length 
    size_t len = strlen(buffer); 

    //x : store converted char to int, rand_num : random number , index of data array 
    int x , rand_num , index = 0; 

    //condition that prevents the program from generating number that is bigger input value 
    bool Condition = 0; 

    //iterate over buffer array 
    for(int n = 0 ; n < len ; n++) 
    { 
     //store the first character of buffer 
     tmp[0] = buffer[n]; 
     tmp[1] = '\0'; 

     //convert it to integer,store in x 
     x = atoi(tmp); 


     if(n == 0) 
     { 
      //if first iteration,rand_num must be less than or equal to x 
      rand_num = rand() % (x + 1); 

      //if generated random number does not equal to x,condition is true 
      if(rand_num != x) 
       Condition = 1; 

      //convert character that corrosponds to integer to integer and store it in data array;increment index 
      data[index] = rand_num + '0'; 
      index++; 
     } 
     //if not first iteration,do the following 
     else 
     { 
      if(Condition) 
      { 
       rand_num = rand() % (10); 

       data[index] = rand_num + '0'; 

       index++; 
      } 
      else 
      { 
       rand_num = rand() % (x + 1); 

       if(rand_num != x) 
        Condition = 1; 

       data[index] = rand_num + '0'; 

       index++; 
      } 
     } 
    } 

    data[index] = '\0'; 

    char *ptr ; 

    //convert the data array to unsigned long long int 
    unsigned long long int ret = _strtoui64(data,&ptr,10); 

    return ret; 
} 
+0

Wie erfüllt das die Anforderung für einen zufälligen 64-Bit-unsigned-Int? –

+0

Nun, ich habe Ihren Code ausprobiert und 1000 Ergebnisse ausgedruckt. Die Ergebnisse sind so; 04951651604868241121, 00651604895168241121, 03943165433604438241, 001604342654656541121 ... also ich denke, wir können nicht haben, was ich mit dieser Methode brauche. –

+0

Sie meinen, Sie wollen nicht die führenden Nullen? –

1

Iff Sie eine ausreichend gute Quelle von zufälligen Bytes haben (wie, sagen wir,/dev/random oder/dev/urandom auf einem Linux-Rechner), können Sie einfach verbrauchen 8 Bytes aus dieser Quelle und verketten sie. Wenn sie unabhängig sind und eine lineare Verteilung haben, sind Sie eingestellt.

Wenn Sie dies nicht tun, können Sie durch dasselbe, aber es ist wahrscheinlich, dass einige Artefakte in Ihrem Pseudo-Zufallsgenerator, der einen Halt für alle Arten von Hallo-Jinx gibt.

Beispielcode vorausgesetzt, wir haben eine offene binäre FILE *source:

/* Implementation #1, slightly more elegant than looping yourself */ 
uint64_t 64bitrandom() 
{ 
    uint64_t rv; 
    size_t count; 

    do { 
    count = fread(&rv, sizeof(rv), 1, source); 
    } while (count != 1); 
    return rv; 
} 

/* Implementation #2 */ 
uint64_t 64bitrandom() 
{ 
    uint64_t rv = 0; 
    int c; 

    for (i=0; i < sizeof(rv); i++) { 
    do { 
     c = fgetc(source) 
    } while (c < 0); 
    rv = (rv << 8) | (c & 0xff); 
    } 
    return rv; 
} 

Wenn Sie mit „get Bytes aus einem Funktionsaufruf“ „zufällige Bytes aus einer Zufälligkeit Gerät lesen“ ersetzen, alles, was Sie tun müssen, ist zu Passe die Verschiebungen in Methode 2 an.

Es ist viel wahrscheinlicher, dass Sie eine "Nummer mit vielen Ziffern" erhalten als eine mit "kleiner Ziffernanzahl" (von allen Zahlen zwischen 0 und 2 ** 64, ungefähr 95% haben 19 oder mehr Dezimalziffern) , so ist das wirklich, was Sie meistens bekommen

+0

Was ist "Hallo-Jinx"? =) –

-2

Wenn Sie 32 oder 16-Bit-Zufallswert haben -. 2 oder 4 randoms erzeugen und sie zu einem 64-Bit mit << und | kombinieren

+0

die Sache ist der zufällige Wert des OP hat nur 30 Bits –

3

In Bezug auf ". Die Ergebnisse sind also immer 18 oder 20 Ziffern. "

Siehe @Thomas comment. Wenn Sie eine Zufallszahl generieren S lang genug, Code wird solche wie 5, 11 und 33387 erstellen. Wenn Code 1.000.000.000 Zahlen/Sekunde generiert, kann es ein Jahr als sehr kleine Zahlen < 100.000 sind so selten unter allen 64-Bit-Nummern.


rand() einfache gibt zufällige Bits zurück. Eine stark vereinfachte Methode zieht 1 Bit zu einer Zeit

uint64_t rand_uint64_slow(void) { 
    uint64_t r = 0; 
    for (int i=0; i<64; i++) { 
    r = r*2 + rand()%2; 
    } 
    return r; 
} 

RAND_MAX Unter der Annahme einig Leistung von 2 - 1, wie in OP Fall 1073741823 == 0x3FFFFFFF, nutzt, dass 30 Bits werden jedes Mal erzeugt. Der folgende Code ruft 3 Mal rand() auf - ein bisschen verschwenderisch. Stattdessen könnten Bits, die herausgeschoben werden, für die nächste Zufallszahl gespeichert werden, aber das bringt andere Probleme mit sich. Lass das für einen anderen Tag.

uint64_t rand_uint64(void) { 
    uint64_t r = 0; 
    for (int i=0; i<64; i += 30) { 
    r = r*((uint64_t)RAND_MAX + 1) + rand(); 
    } 
    return r; 
} 

Tragbares Schleifenzählwert Verfahren vermeidet die 30

#if RAND_MAX/256 >= 0xFFFFFFFFFFFFFF 
    #define LOOP_COUNT 1 
#elif RAND_MAX/256 >= 0xFFFFFF 
    #define LOOP_COUNT 2 
#elif RAND_MAX/256 >= 0x3FFFF 
    #define LOOP_COUNT 3 
#elif RAND_MAX/256 >= 0x1FF 
    #define LOOP_COUNT 4 
#else 
    #define LOOP_COUNT 5 
#endif 

uint64_t rand_uint64(void) { 
    uint64_t r = 0; 
    uint64_t r = 0; 
    for (int i=LOOP_COUNT; i > 0; i--) { 
    r = r*(RAND_MAX + (uint64_t)1) + rand(); 
    } 
    return r; 
} 

Die Autokorrelationseffekte kommentierte here durch eine schwache rand() verursacht werden. C spezifiziert keine bestimmte Methode der Zufallszahlenerzeugung. Das Obige stützt sich auf rand() ist gut. Wenn rand() untergeordnet ist, sollte der Code andere Generatoren und rand() verwenden.

+2

Diese Antwort ist wie ein Gedicht. Ich meine die Erklärungen. Ich habe alles verstanden, was mit meiner Frage zusammenhängt. –

0

Ich habe diesen Code here versucht und es scheint gut zu funktionieren.

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

int main(){ 
    srand(time(NULL)); 
    int a = rand(); 
    int b = rand(); 
    int c = rand(); 
    int d = rand(); 
    long e = (long)a*b; 
    e = abs(e); 
    long f = (long)c*d; 
    f = abs(f); 

    long long answer = (long long)e*f; 

    printf("value %lld",answer); 
    return 0; 
} 

lief ich ein paar Wiederholungen und ich bekomme folgende Ausgänge:

Wert 1869044101095834648
Wert 2104046041914393000

Wert 1587782446298476296
Wert 604955295827516250
Wert 41152208336759610
Wert 57792837533816000

0

Wenn Sie nicht über eine sich wiederholende Pseudozufallsfolge dagegen (hey, für 64 Bits werden Sie nicht die Wiederholung in Ihrem Leben gehen zu bemerken;) und Sie können befassen sich mit einem Wert kleiner als die gewünschte Reichweite (0 wird nicht passieren), eine LCG oder MCG ist eine erstaunlich einfache Lösung. Wikipedia: Linear congruential generator Gehen Sie zu here, um einige Primzahlen zu generieren, und verwenden Sie eine für den Modulus und die andere für den unten angegebenen Multiplikator. (Einschränkung: diese Sequenz wird zu erraten sein und somit ist es nicht sicher ist)

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

uint64_t 
mcg64(void) 
{ 
    static uint64_t i = 1; 
    return (i = (164603309694725029ull * i) % 14738995463583502973ull); 
} 

int 
main(int ac, char * av[]) 
{ 
    for (int i = 0; i < 10; i++) 
     printf("%016p\n", mcg64()); 
}