Warum erhalte ich mit rand() immer dieselbe Folge von Zufallszahlen?

Lesezeit: 7 Minuten

Benutzeravatar von Hannoun Yassir
Hannum Jassir

Dies ist das erste Mal, dass ich Zufallszahlen mit C versuche (ich vermisse C#). Hier ist mein Code:

int i, j = 0;
for(i = 0; i <= 10; i++) {
    j = rand();
    printf("j = %d\n", j);
}

Mit diesem Code erhalte ich jedes Mal dieselbe Sequenz, wenn ich den Code ausführe. Aber es erzeugt verschiedene zufällige Sequenzen, wenn ich hinzufüge srand(/*somevalue/*) Vor dem for Schleife. Kann jemand erklären warum?

  • Nur als Nebenknoten: rand()-Implementierungen sind normalerweise ziemlich schlecht. Das bedeutet kurze Wiederholungszyklen und Zufallszahlen geringer Qualität. Ich würde also ein PRNG eines Drittanbieters verwenden und nicht das in Ihrer Laufzeit enthaltene.

    – CodesInChaos

    12. Oktober 2010 um 20:09 Uhr

  • srand() — warum nur einmal aufrufen?

    – phuklv

    30. April 2017 um 9:58 Uhr

  • Siehe auch Empfohlene Initialisierungsmethode srand()?

    – Jonathan Leffler

    22. April um 15:28 Uhr

Benutzeravatar von kjfletch
kjfletch

Du musst es aussäen. Es ist eine gute Idee, es mit der Zeit zu säen:

srand()

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

int main ()
{
  srand ( time(NULL) );
  printf ("Random Number: %d\n", rand() %100);
  return 0;
}

Sie erhalten die gleiche Sequenz, weil rand() wird automatisch mit dem Wert 1 gesät, wenn Sie nicht callen srand().

Bearbeiten

Aufgrund von Kommentaren

rand() gibt eine Zahl zwischen 0 und zurück RAND_MAX (definiert in der Standardbibliothek). Verwendung der modulo Operator (%) ergibt den Rest der Division rand() / 100. Dadurch wird die Zufallszahl in den Bereich 0-99 gezwungen. Um beispielsweise eine Zufallszahl im Bereich von 0-999 zu erhalten, würden wir uns bewerben rand() % 1000.

  • Ich weiß das bereits, aber meine Frage ist, warum gibt es die gleiche Sequenz, wenn ich nicht srand verwende?

    – Hannun Jassir

    10. Juli 2009 um 10:29 Uhr

  • Denn wenn Sie es nicht manuell aussäen, ist es das STETS standardmäßig auf 1 gesetzt. Siehe Adityas Antwort.

    – GManNickG

    10. Juli 2009 um 10:41 Uhr

  • Wenn die Sicherheit ein Problem darstellt, ist es eine ziemlich schlechte Idee, sie mit der Zeit zu impfen, da ein Angreifer die Startzeit oft relativ leicht finden oder erraten kann (innerhalb einiger Dutzend bis einiger hundert Versuche) und dann Ihre Folge von Pseudozufallszahlen wiedergibt. Versuchen Sie, wenn möglich, stattdessen eine vom Betriebssystem bereitgestellte Entropiequelle für Ihren Seed zu verwenden.

    – Dave Sherohmann

    10. Juli 2009 um 10:46 Uhr

  • Wenn die Sicherheit ein Problem darstellt, ist die Verwendung von rand() überhaupt eine ziemlich schlechte Idee, egal wie Sie sie einsetzen. Abgesehen von der unbekannten Stärke des PRNG-Algorithmus benötigt er im Allgemeinen nur 32 Bit Seed, sodass Brute Force plausibel ist, selbst wenn Sie es sich nicht besonders einfach machen, indem Sie mit der Zeit Seeding durchführen. Das Seeding von rand() mit einer Entropiequelle für die Sicherheit ist, als würde man einem Esel Steroide geben und es in die eingeben [Kentucky] Derby.

    – Steve Jessop

    10. Juli 2009 um 11:27 Uhr

  • „Zum Beispiel, um eine Zufallszahl im Bereich von 0-999 zu erhalten, würden wir rand()%1000 anwenden.“ Seien Sie gewarnt, das Ergebnis ist nicht gleichmäßig verteilt, es sei denn, 1000 teilt sich gleichmäßig in RAND_MAX+1 (was wahrscheinlich nicht der Fall ist RAND_MAX ist oft (2^n)-1), und es gibt auch eine ganze Menge anderer Probleme. Sehen amillionmonkeys.com/qed/random.html

    – Boanne

    21. Juni 2013 um 9:41 Uhr


Benutzeravatar von nos
Nr

rand() kehrt zurück pseudozufällig Zahlen. Es generiert Zahlen basierend auf einem bestimmten Algorithmus.

Der Ausgangspunkt dieses Algorithmus ist immer derselbe, sodass für jeden Aufruf dieselbe Sequenz generiert wird. Dies ist praktisch, wenn Sie das Verhalten und die Konsistenz Ihres Programms überprüfen müssen.

Sie können den “Samen” des Zufallsgenerators mit einstellen srand Funktion (nur aufrufen srand einmal in einem Programm) Eine gängige Methode, um verschiedene Sequenzen aus dem zu erhalten rand() Generator soll den Startwert auf die aktuelle Zeit oder die ID des Prozesses setzen:

srand(time(NULL)); oder srand(getpid()); zu Beginn des Programms.

Das Generieren von echtem Zufall ist für einen Computer sehr, sehr schwierig, aber für praktische, nicht kryptobezogene Arbeiten funktioniert ein Algorithmus, der versucht, die generierten Sequenzen gleichmäßig zu verteilen, gut.

  • Wie bekomme ich getpid()? Brauche ich eine spezielle Bibliothek?

    – Hallo

    21. April 2018 um 13:11 Uhr

  • @Hallo #include <unistd.h>

    – ggorlen

    26. Oktober 2021 um 21:20 Uhr

Benutzeravatar von Aditya Sehgal
Aditya Sehgal

Aus zu zitieren Mann Rand :

Die srand()-Funktion legt ihr Argument als Startwert für eine neue Folge pseudozufälliger Ganzzahlen fest, die von rand() zurückgegeben werden. Diese Sequenzen sind wiederholbar, indem srand() mit demselben Seed-Wert aufgerufen wird.

Wenn kein Seed-Wert angegeben wird, wird die rand()-Funktion automatisch mit einem Wert von 1 gesät.

Also, ohne Startwert, rand() nimmt den Seed als 1 an (jedes Mal in Ihrem Fall) und mit dem gleichen Seed-Wert, rand() ergibt die gleiche Zahlenfolge.

Hier gibt es viele Antworten, aber niemand scheint sie zu haben Ja wirklich erklärt, warum rand() bei gleichem Seed immer die gleiche Sequenz generiert – oder sogar, was der Seed wirklich tut. Hier geht es also.

Die Funktion rand() behält einen internen Zustand bei. Konzeptionell könnten Sie sich dies als eine globale Variable eines Typs namens rand_state vorstellen. Jedes Mal, wenn Sie rand() aufrufen, werden zwei Dinge ausgeführt. Es verwendet den vorhandenen Zustand, um einen neuen Zustand zu berechnen, und es verwendet den neuen Zustand, um eine Zahl zu berechnen, die an Sie zurückgegeben wird:

state_t rand_state = INITIAL_STATE;

state_t calculate_next_state(state_t s);
int calculate_return_value(state_t s);

int rand(void)
{
    rand_state = calculate_next_state(rand_state);
    return calculate_return_value(rand_state);
}

Jetzt können Sie sehen, dass jedes Mal, wenn Sie rand() aufrufen, rand_state dazu veranlasst wird, sich einen Schritt entlang eines vordefinierten Pfads zu bewegen. Die zufälligen Werte, die Sie sehen, basieren nur darauf, wo Sie sich auf diesem Pfad befinden, also folgen sie auch einer vorbestimmten Reihenfolge.

Hier kommt jetzt srand() ins Spiel. Damit können Sie zu einem anderen Punkt auf dem Pfad springen:

state_t generate_random_state(unsigned int seed);

void srand(unsigned int seed)
{
    rand_state = generate_random_state(seed);
}

Die genauen Details von state_t, compute_next_state(), compute_return_value() und generate_random_state() können von Plattform zu Plattform variieren, sind aber normalerweise recht einfach.

Sie können daraus ersehen, dass rand_state jedes Mal, wenn Ihr Programm startet, bei INITIAL_STATE beginnt (was äquivalent zu generate_random_state(1) ist) – weshalb Sie immer dieselbe Sequenz erhalten, wenn Sie srand() nicht verwenden.

Wenn ich mich an das Zitat aus Knuths wegweisendem Werk „The Art of Computer Programming“ am Anfang des Kapitels zur Zufallszahlengenerierung erinnere, geht es so:

„Jeder, der versucht, Zufallszahlen mit mathematischen Mitteln zu erzeugen, befindet sich technisch gesehen in einem Zustand der Sünde.“

Einfach ausgedrückt, die Aktiengeneratoren für Zufallszahlen sind Algorithmen, mathematisch und zu 100 % vorhersehbar. Dies ist in vielen Situationen eine gute Sache, in denen eine wiederholbare Folge von “Zufallszahlen” wünschenswert ist – zum Beispiel für bestimmte statistische Übungen, bei denen Sie das “Wackeln” der Ergebnisse vermeiden möchten, das dank echter Zufallsdaten entsteht Clustering-Effekte.

Obwohl das Erfassen von “zufälligen” Daten von der Hardware des Computers eine beliebte zweite Alternative ist, ist es auch nicht wirklich zufällig – obwohl je komplexer die Betriebsumgebung, desto mehr Möglichkeiten für Zufälligkeit – oder zumindest Unvorhersehbarkeit.

Wirklich zufällige Datengeneratoren neigen dazu, sich an externen Quellen zu orientieren. Radioaktiver Zerfall ist ein Favorit, ebenso wie das Verhalten von Quasaren. Alles, was seine Wurzeln in Quanteneffekten hat, ist praktisch zufällig – sehr zu Einsteins Ärger.

Benutzeravatar von Dave Sherohman
David Sherohmann

Zufallszahlengeneratoren sind nicht wirklich zufällig, sie sind wie die meisten Software vollständig vorhersehbar. Rand erzeugt jedes Mal eine andere Pseudo-Zufallszahl, wenn sie Eins genannt wird, was zufällig erscheint. Um es richtig zu verwenden, müssen Sie ihm einen anderen Ausgangspunkt geben.

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

int main ()
{
  /* initialize random seed: */
  srand ( time(NULL) );

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

  return 0;
}

Benutzeravatar von Key
Taste

Das ist von http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.13.html#rand:

Erklärung:

void srand(unsigned int seed); 

Diese Funktion startet den Zufallszahlengenerator, der von der Funktion rand verwendet wird. Das Seeding von srand mit demselben Seed führt dazu, dass rand dieselbe Folge von Pseudozufallszahlen zurückgibt. Wenn srand nicht aufgerufen wird, verhält sich rand so, als ob srand(1) aufgerufen worden wäre.

1415080cookie-checkWarum erhalte ich mit rand() immer dieselbe Folge von Zufallszahlen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy