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.)
Wahrscheinlich nicht der sauberste Weg, aber Sie können es schaffen, indem Sie clojure.core/rand
neu definieren:
Dies erzeugt (5 8 7 3 4 4 4 6 8 8) jedes Mal, wenn ich es laufe.
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% Clojures rand
basiert auf der Methode random
in java.lang.Math
:
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 Pseudozufallszahlengeneratornew 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*
:
Verwenden Sie gen/*rnd*
wie in diesem Beispiel gezeigt:
Dies gibt immer -593551136
zurück.
In der ursprünglichen Frage werden zwei Dinge falsch verstanden:
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:
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%Tags und Links clojure