2010-06-18 16 views
11

Während für Tutorials auf der Generierung von Zufallszahlen in CI Suche gefunden this topicErzeugung von Zufallszahlen in C

Wenn ich versuche, die rand() Funktion ohne Parameter zu verwenden, I 0 immer, wenn ich versuche, die rand() Funktion mit Parametern zu verwenden, , Bekomme ich immer den Wert 41. Und wenn ich versuche, arc4random() und random() Funktionen zu verwenden, bekomme ich einen LNK2019 Fehler.

Hier ist, was ich getan habe:

#include <stdlib.h> 
int main() 
{ 
    int x; 
    x = rand(6); 
    printf("%d", x); 
} 

Dieser Code immer 41 erzeugt Wohin gehe ich falsch? Ich verwende Windows XP SP3 und verwende die VS2010-Eingabeaufforderung als Compiler.

+0

versuchen Sie 'rand() * 10' – deostroll

Antwort

30

Sie sollten srand() aufrufen, bevor Sie rand aufrufen, um den Zufallsgenerator zu initialisieren.

Entweder es mit einem bestimmten Samen nennen, und Sie erhalten die gleiche Pseudozufallsfolge

#include <stdlib.h> 

int main() 
{ 
    srand (123); 
    int random_number = rand(); 
    return 0; 
} 

oder rufen Sie es mit einer sich verändernden Quellen, dh die Zeitfunktion

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

int main() 
{ 
    srand (time(NULL)); 
    int random_number = rand(); 
    return 0; 
} 

immer erhalten Als Antwort auf Moons Kommentar rand() generiert eine Zufallszahl mit einer gleichen Wahrscheinlichkeit zwischen 0 und RAND_MAX (ein Makro in stdlib.h vordefiniert)

Sie können diesen Wert dann einem kleineren Bereich zuordnen, z.

int random_value = rand(); //between 0 and RAND_MAX 

//you can mod the result 
int N = 33; 
int rand_capped = random_value % N; //between 0 and 32 
int S = 50; 
int rand_range = rand_capped + S; //between 50 and 82 

//you can convert it to a float 
float unit_random = random_value/(float) RAND_MAX; //between 0 and 1 (floating point) 

Dies könnte für die meisten Anwendungen ausreichend sein, aber es ist darauf hinzuweisen, dass im ersten Fall die Bedienungsperson eine leichte mod Bias führt zu verwenden, wenn N teilt sich nicht gleichmäßig in RAND_MAX + 1.

Zufallszahlengeneratoren sind interessant und komplex, es wird weithin gesagt, dass der Rand() Generator in der C-Standard-Bibliothek keine große Qualität Zufallszahlengenerator ist, lesen (http://en.wikipedia.org/wiki/Random_number_generation für eine Definition von Qualität).

http://en.wikipedia.org/wiki/Mersenne_twister (source http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html) ist eine beliebte hochwertige Zufallszahlengenerator.

Auch ich bin nicht bekannt arc4rand() oder random(), also kann ich nicht kommentieren.

+1

Danke. Aber immer noch, zwei Fragen bleiben. 1) Was soll ich tun, wenn ich Zufallszahlen in einem bestimmten Bereich erzeugen will, sagen wir 0 bis 9? Ich habe 'rand (10)' versucht, aber es hat nicht geholfen. 2) Was war das Problem mit mir 'arc4rand()' und 'random()'? – MoonStruckHorrors

+0

Ausgezeichnet. Nochmals vielen Dank. – MoonStruckHorrors

5

Sie müssen Ihren PRNG so säen, dass er jedes Mal mit einem anderen Wert beginnt.

Eine einfache, aber niedrige Qualität Samen ist die aktuelle Zeit zu nutzen:

srand(time(0)); 

Das wird Ihnen den Einstieg aber gilt geringer Qualität (dh zum Beispiel, verwenden Sie nicht, wenn Sie versuchen, RSA-Schlüssel zu generieren).

Hintergrund. Pseudozufallszahlengeneratoren erzeugen keine echten Zufallszahlenfolgen, sondern simulieren sie nur. Wenn Sie eine Startpunktnummer angeben, gibt ein PRNG immer die gleiche Zahlenfolge zurück. Standardmäßig beginnen sie mit demselben internen Status und geben dieselbe Sequenz zurück.

Um nicht die gleiche Sequenz zu erhalten, ändern Sie den internen Status. Der Vorgang des Änderns des internen Zustands wird "Seeding" genannt.

1

Sie müssen zuerst seed der Generator, weil es nicht generiert echte Zufallszahlen!

Versuchen Sie folgendes:

#include <stdlib.h> 
#include <time.h> 
int main() 
{ 
    // random seed, time! 
    srand(time(NULL)); // hackish but gets the job done. 
    int x; 
    x = rand(); // everytime it is different because the seed is different. 
    printf("%d", x); 
} 
+0

Es kann nicht anders sein ** jedes Mal, wenn Sie den Code ausführen (versuchen Sie, Ihren Code in einer Bash-Schleife auszuführen, während "true; do ./prog; done"). Raymond Chens Blog-Eintrag ist heute zufällig über genau dieses Problem erschienen (http://blogs.msdn.com/b/oldnewthing/archive/2010/06/17/10026183.aspx) –

+0

Danke. Eine gute Lektüre in der Tat. – AraK

3
#include <stdlib.h> 

int main() 
{ 
    int x; 
    x = rand(6); 
    printf("%d", x); 
} 

Gerade als Anfänger, sollten Sie Ihren Compiler fragen jede Warnung über schlechten Code zu drucken, die sie erzeugen kann. Moderne Compiler kennen viele verschiedene Warnungen, die Ihnen helfen, besser zu programmieren. Zum Beispiel, wenn Sie dieses Programm mit dem GNU C Compiler kompilieren:

$ gcc -W -Wall rand.c 
rand.c: In function `main': 
rand.c:5: error: too many arguments to function `rand' 
rand.c:6: warning: implicit declaration of function `printf' 

Sie erhalten hier zwei Warnungen. Der erste sagt, dass die rand Funktion nur Null Argumente, nicht eins, wie Sie versucht haben. Um eine zufällige Zahl zwischen 0 und n zu erhalten, können Sie den Ausdruck rand() % n verwenden, der nicht perfekt ist, aber ok für kleine n. Die resultierenden Zufallszahlen sind normalerweise nicht gleichmäßig verteilt; kleinere Werte werden häufiger zurückgegeben.

Die zweite Warnung besagt, dass Sie eine Funktion aufrufen, die der Compiler zu diesem Zeitpunkt nicht kennt. Sie müssen dem Compiler sagen: #include <stdio.h>. Welche Include-Dateien für welche Funktionen benötigt werden, ist nicht immer einfach, aber die Open Group-Spezifikation für portable Betriebssysteme zu verwenden funktioniert in vielen Fällen: http://www.google.com/search?q=opengroup+rand.

Diese beiden Warnungen informieren Sie sehr über die Geschichte der C-Programmiersprache. Vor 40 Jahren umfasste die Definition einer Funktion nicht die Anzahl der Parameter oder die Arten der Parameter. Es war auch in Ordnung, eine unbekannte Funktion aufzurufen, die in den meisten Fällen funktionierte. Wenn Sie heute Code schreiben möchten, sollten Sie sich nicht auf diese alten Funktionen verlassen, sondern stattdessen die Warnungen Ihres Compilers aktivieren, die Warnungen verstehen und sie dann ordnungsgemäß beheben.

3

Auch linearen Kongruenz PRNGs neigen dazu, mehr Zufälligkeit auf den höheren Bits zu erzeugen, die auf den unteren Bits, so das Ergebnis der Kappe nicht Modulo verwenden, sondern so etwas wie verwenden:

j = 1 + (int) (10.0 * (rand()/(RAND_MAX + 1.0))); 

(Diese ist von "Numerical Recipes in C", Ch.7)

1

Oder eine Pseudozufall int im Bereich von 0 bis 19, zum Beispiel zu bekommen, um die höheren Bits wie diese verwenden:

j = ((rand() >> 15) % 20; 
+1

Warum die '>> 15'? In einigen Implementierungen ist "RAND_MAX" nur "0x7fff", so dass die Verschiebung eines Zufallswertes um diesen Betrag immer "0" wäre. –

1
int *generate_randomnumbers(int start, int end){ 
    int *res = malloc(sizeof(int)*(end-start)); 
    srand(time(NULL)); 
    for (int i= 0; i < (end -start)+1; i++){ 
     int r = rand()%end + start; 
     int dup = 0; 
     for (int j = 0; j < (end -start)+1; j++){ 
      if (res[j] == r){ 
       i--; 
       dup = 1; 
       break; 
      } 
     } 
     if (!dup) 
      res[i] = r; 
    } 
    return res; 
}