Frage

Ich habe nicht Impfen Pseudozufallszahlengeneratoren mehr als einmal pro Ausführung schon einige Empfehlungen gesehen, aber nie durch eine gründliche Erklärung begleitet. Natürlich ist es leicht, das folgende (C / C ++) Beispiel zu sehen, warum nicht eine gute Idee ist:

int get_rand() {
  srand(time(NULL));
  return rand();
}

da get_rand mehrmals pro Sekunde Aufruf führt zu Ergebnissen wiederholt.

Aber wäre nicht das folgende Beispiel noch eine akzeptable Lösung sein?

MyRand.h

#ifndef MY_RAND_H
#define MY_RAND_H

class MyRand
{
  public:
    MyRand();
    int get_rand() const;
  private:
    static unsigned int seed_base;
};

#endif

MyRand.cpp

#include <ctime>
#include <cstdlib>
#include "MyRand.h"

unsigned int MyRand::seed_base = static_cast<unsigned int>(time(NULL));

MyRand::MyRand()
{
  srand(seed_base++);
}

int MyRand::get_rand() const
{
  return rand();
}

main.cpp

#include <iostream>
#include "MyRand.h"

int main(int argc, char *argv[]) 
{
  for (int i = 0; i < 100; i++) 
  {
    MyRand r;
    std::cout << r.get_rand() << " ";
  }
}

d. obwohl MyRand: Konstruktor mehrmals schnell hintereinander aufgerufen wird, hat jeder Aufruf srand einen anderen Parameter. Offensichtlich ist dies nicht Thread-sicher, aber dann wieder weder rand ist.

War es hilfreich?

Lösung

Jedes Mal, wenn Sie eine Pseudo-Zufallszahlengenerator-Funktion aufrufen, nimmt der Generator einige interne Zustand und erzeugt eine Pseudozufallszahl und einen neuen internen Zustand. Der Algorithmus für den internen Zustand Umwandlung sorgfältig ausgewählt wird, um die Ausgabe zufällig erscheint.

Wenn Sie den Zufallszahlengenerator Samen, Sie Einstellung im Grunde diesen inneren Zustand. Wenn Sie den internen Zustand zu einem gewissen vorhersagbaren Wert zurückgesetzt, werden Sie das Aussehen des Zufalls verlieren.

Zum Beispiel eine beliebte, einfache RNG ist ein Kongruenzgenerator. Die Zahlen werden wie folgt generiert:

X[n+1] = (a X[n] + c) mod m

In diesem Fall X [n + 1] ist sowohl das Ergebnis und der neue interne Zustand. Wenn Sie den Generator jedes Mal, Samen, wie Sie oben vorschlagen, erhalten Sie eine Sequenz erhalten, die wie folgt aussieht:

{(ab + c) mod m, (a(b+1) + c) mod m, (a(b+2) + c) mod m, ...}

, wobei b Ihre seed_base. Dies gilt nicht zufällig aussehen überhaupt.

Andere Tipps

Wenn Ihr Samen vorhersehbar ist, was es hier ist, da Sie es gerade erst erhöht wird, wird die Ausgabe von rand () auch vorhersehbar sein.

Es hängt wirklich davon ab, warum wollen Sie Zufallszahlen zu erzeugen, und wie „random“ ist eine akzeptable zufällig für Sie. In Ihrem Beispiel kann es Duplikate in schnellen Folge vermeiden, und das kann für Sie gut genug sein. Immerhin was zählt, ist, dass es ausgeführt wird.

Auf fast jeder Plattform gibt es eine bessere Art und Weise Zufallszahl als Rand zu erzeugen ().

Nun, es ist eine zusätzliche Verarbeitung, die nicht getan werden muss.

In diesem Szenario würde ich rufen Sie einfach den Konstruktor einmal mit einem zeitbasierten Samen vor dem Beginn der Schleife. Das wird garantiert zufällige Ergebnisse ohne zusätzlichen Aufwand von Samen für jede Iteration zu ändern.

Ich würde nicht denken, dass Ihre Methode ist jedes mehr zufällig als das.

Sie können denken Erzeugung von Zufallszahlen (dies ist nicht unbedingt wahr ist umsetzungs weise mehr, sondern dient als Illustration) als Wertetabelle. Wenn Sie tun, alle diese Dinge in der Statistik zu tun einfachen Stichproben erinnern, ein Samen im Grunde sagt Ihnen, welche Zeile und Spalte an in Ihrem großen Tabelle von Zufallszahlen zu beginnen. Nachsaat immer und immer wieder ist einfach nicht notwendig, da wir bereits, dass die Zahlen annehmen können in der Regel bereits verteilt sind.

Es gibt einfach keinen zusätzlichen Nutzen mehr als einmal Aussaat, da dies gut genug sein sollte (je nach Anwendung). Wenn Sie „mehr“ Zufallszahlen benötigen, gibt es viele Methoden der Erzeugung von Zufallszahlen. Ein Fall, den ich denken kann ist, Zufallszahl in einem Thread-sichere Art und Weise zu erzeugen.

Während Ihre Lösung akzeptabel ist, werden Ihre Zahlen nicht mehr zufällig, als es einmal Impfen, global. srand im Allgemeinen sollte nicht in einem Konstruktor gehören. Wenn Sie möchten, um Zufallszahlen unterstützen, sobald Samen, wenn das Programm startet, und vergessen Sie es.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top