Wie wiederholbare Zufallsfolgen mit rand-int erzeugt werden

8

Ich möchte wiederholbare Zahlen mit rand in Clojure erzeugen können. (Insbesondere möchte ich, dass die Ergebnisse von Aufrufen von rand-nth oder Incancers sample wiederholbar sind, und diese Aufrufe rand-int , was wiederum rand aufruft.)

Ich fand heraus, dass Frage , dass, wenn ich clojure.data.generators verwende, ich den Zufallszustand zurücksetzen kann:

%Vor%

Diese Methode scheint jedoch nur Funktionen in clojure.data.generators zu beeinflussen, was nicht überraschend ist:

%Vor%

Wie kann ich den Zufallszustand wiederherstellen, um wiederholbare Ergebnisse von rand zu erhalten? Bisher habe ich keine Dokumentation darüber gefunden.

( Eine andere Frage klingt, als ob es sein könnte das gleiche Problem, aber es fragt nach etwas völlig anderem.)

    
Mars 03.06.2014, 04:20
quelle

6 Antworten

4

Wahrscheinlich nicht der sauberste Weg, aber Sie können es schaffen, indem Sie clojure.core/rand neu definieren:

%Vor%

Dies erzeugt (5 8 7 3 4 4 4 6 8 8) jedes Mal, wenn ich es laufe.

    
Diego Basch 03.06.2014 04:48
quelle
2

Hier können Sie den Funktionsgenerator definieren, den Sie erzeugen können, den ich in den Kommentaren beschrieben habe.

Wenn Sie keine Doppelgänger wollen, schauen Sie in die Javadoc .

%Vor%

So können Sie es mit einem Zufallszahlengenerator erzeugen.

%Vor%

Als Bonus könntest du auch das neue ThreadLocalRandom oder die nicht ganz neue SecureRandom als Ihre zufällige Nummer Generatoren.

%Vor%     
Bill 03.06.2014 20:16
quelle
2

Ein sauberer Weg:

%Vor%

Definiert rand im Geltungsbereich neu. Beispiel:

%Vor%

Übrigens. Vorsicht vor Lazy Seqs: Ссылка (Offensichtlich leitet dieser Link zu https ohne ein vertrauenswürdiges Zertifikat um, hier ist ein Link zu einer Version im Web Archive: Ссылка ).

    
Marcin Bilski 24.07.2014 10:12
quelle
2

Clojures rand basiert auf der Methode random in java.lang.Math :

%Vor%

Laut Oracle Java 7-Dokumentation unter Ссылка

  

public static double random ()

     

Gibt einen doppelten Wert mit einem positiven Vorzeichen, größer als oder gleich 0.0 und kleiner als 1.0 zurück. Zurückgegebene Werte werden pseudozufällig mit (annähernd) gleichmäßiger Verteilung aus diesem Bereich gewählt.

     

Wenn diese Methode zum ersten Mal aufgerufen wird, erzeugt sie genau wie durch den Ausdruck

einen neuen Pseudozufallszahlengenerator      

new java.util.Random ()

     

Dieser neue Pseudozufallszahlengenerator wird danach für alle Aufrufe dieser Methode verwendet und nirgendwo sonst verwendet.

     

Diese Methode wird ordnungsgemäß synchronisiert, um die korrekte Verwendung durch mehr als einen Thread zu ermöglichen. Wenn jedoch viele Threads Pseudozufallszahlen mit einer hohen Rate erzeugen müssen, kann dies die Konkurrenz für jeden Thread reduzieren, der einen eigenen Pseudozufallszahlengenerator hat.

     

Rückkehr:

     

ein Pseudozufallsdoppel größer als oder gleich 0.0 und kleiner als 1.0.

Wenn Sie die java.lang.Math -Dokumentation durchsuchen, werden Sie feststellen, dass keine API zur Verfügung steht, um das Setzen eines Zufallszahlengenerators zu erlauben. Code, der die random() API verwendet, kann nicht den Seed oder die verschiedenen Kopien des Zufallszahlengenerators festlegen.

Die ursprüngliche Frage war:

  

Ich möchte wiederholbare Zahlen mit rand in Clojure erzeugen können.   [z.B. clojure.core / rand]

Dies ist nicht möglich, es sei denn, Sie verwenden Ihre eigene Rand-Funktion. Also, anstatt clojure.core/rand , schlage ich vor, clojure.data.generators zu verwenden, was den Zufallszahlengenerator als dynamische Variable ausstellt *rnd* :

%Vor%

Verwenden Sie gen/*rnd* wie in diesem Beispiel gezeigt:

%Vor%

Dies gibt immer -593551136 zurück.

    
David J. 29.11.2014 17:11
quelle
1

In der ursprünglichen Frage werden zwei Dinge falsch verstanden:

  • Wie man dynamische vars benutzt
  • Wie benutzt man clojure.data.generators
  • ?

Erstens sollten dynamische vars über das Makro binding verwaltet werden. Der zweite rand ist keine Funktion von clojure.data.generators , sondern von clojure.core selbst und somit hat das Zurücksetzen von *rnd* var keinen Effekt. Also hier ist, wie Sie es tun sollten:

%Vor%     
Jeroen van Dijk 08.10.2014 09:41
quelle
0

Soweit ich weiß, sind keine der oben genannten Ansätze funktional. Wenn Sie das wollen, können Sie einen Lazy-Seq verwenden:

%Vor%

So erhalten Sie die erste Zufallszahl, die Sie verwenden:

%Vor%

Um den Rest der Sequenz zu erhalten, die Sie verwenden:

%Vor%

Um das erste Element und einen Verweis auf den Rest zu erhalten, können Sie verwenden:

%Vor%     
Joerg Schmuecker 11.07.2017 03:40
quelle

Tags und Links