2010-08-27 2 views
5

Die Klasse Random in Ruby 1.9.2 generiert garantiert Zufallszahlen in der gleichen Reihenfolge, mit einem bestimmten Seed und Bereich. Zum Beispiel:Verteilte sequentielle Zufallszahlengenerierung in Ruby 1.9.2

r = Random.new(23) 
r.rand(100)   # 83 
r.rand(100)   # 40 

Aber ich nehme an die nächste Zahl in der Folge auf einem anderen Computer (ohne erneute Erzeugung der früheren Nummern in der Reihenfolge) generieren möchten. Dies sollte angesichts der vorherigen Ausgabe möglich sein. Gibt es eine Möglichkeit, dies mit der Klasse Random zu tun? Oder muss ich meine eigene Implementierung des Mersenne twister schreiben?

[Edit: Wie unten in den Kommentaren darauf hingewiesen, es ist in der Tat nicht möglich, den Zustand einer Random Instanz zu bestimmen, nur von dem Ausgang, da nur einen Teil des Staates (genauer gesagt, die niedrigen 32 Bits) werden für die Ausgabe verwendet.]

+0

Warum sollte es möglich sein, dies zu tun? – adamse

+0

@adamse Die nächste Zahl wird deterministisch bei gegebenem internen Zustand in 'r' erzeugt. Wenn Sie also ein neues "r" mit demselben Status wie das alte erstellen, wird die nächste Zahl in der Sequenz generiert. Macht Sinn? Basierend auf meinem Verständnis der Algorithmen, die "Random" zugrunde liegen, glaube ich, dass dieser Zustand durch den Seed und die letzte generierte Zahl repräsentiert werden kann. –

+0

lesen die [backported] (http://github.com/marcandre/backports/blob/master/lib/backports/1.9.2/random/MT19937.rb) Implementierung scheint es, dass Sie in der Tat finden Sie den nächsten Zustand mit der zuletzt und der Samen. Soweit ich weiß, können Sie den Status aufgrund der generierten Nummer jedoch nicht finden. – adamse

Antwort

2

Kann nicht getestet werden, aber der Generator kann laut Marc-André Lafortune here gemarshallt werden. So könnte das funktionieren:

r = Random.new(23) 
r.rand(100)   # 83 
r.rand(100)   # 40 

File.open("/path/to/file","w") do |f| 
    Marshal.dump(r,f) 
end 

# later, may be on another computer 

File.open("/path/to/file","r") do |f| 
    @v = Marshal.load(f) 
end 

puts @v.rand(100) 
+0

Das könnte funktionieren, aber das scheint furchtbar ineffizient. Im Prinzip sollten Sie nur den zuletzt erzeugten Wert von einem Computer zum anderen übertragen müssen; Sie sollten das gesamte Objekt nicht serialisieren müssen. –

+1

Sie machen die Annahme, dass es keinen anderen internen Zustand gibt. Du könntest sicherlich einen Zufallszahlengenerator schreiben, für den das stimmt (einfachste Methode: wiederhole Zufall mit der vorherigen Zahl als Startwert und benutze nur den ersten Aufruf), aber es ist nicht wirklich fair zu sagen, dass die aktuelle Random-Klasse " sollte im Prinzip die Staatenlosigkeit für einen ungewöhnlichen Anwendungsfall aufrechterhalten. – SFEley