2010-08-27 25 views
5

La classe Random in Ruby 1.9.2 è garantita per generare numeri casuali nello stesso ordine, dati un particolare seme e intervallo. Per esempio:Generazione sequenziale di numeri casuali distribuiti in Ruby 1.9.2

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

Ma supponiamo che io voglio per generare il numero successivo nella sequenza su un altro computer (senza ri-generare i numeri precedenti nella sequenza). Questo dovrebbe essere possibile, dato l'output precedente. C'è un modo per farlo con la classe Random? O devo scrivere la mia implementazione dello Mersenne twister?

[Edit: Come sottolineato nei commenti qui sotto, non è infatti possibile determinare lo stato di un'istanza Random appena dall'uscita, perché solo parte dello stato (in particolare, i bassi 32 bit) vengono utilizzati per l'output.]

+0

Perché dovrebbe essere possibile farlo? – adamse

+0

@adamse Il numero successivo viene generato deterministicamente in base allo stato interno in 'r'. Quindi se crei un nuovo 'r' con lo stesso stato di quello vecchio, genererà il numero successivo nella sequenza. Ha senso? Sulla base della mia comprensione degli algoritmi alla base di 'Random', credo che questo stato possa essere rappresentato dal seme e dall'ultimo numero generato. –

+0

leggendo l'implementazione [backported] (http://github.com/marcandre/backports/blob/master/lib/backports/1.9.2/random/MT19937.rb) sembra che in effetti tu possa trovare lo stato successivo usando il l'ultimo e il seme. Tuttavia, per quanto ho capito, potresti non essere in grado di trovare lo stato dato il numero generato. – adamse

risposta

2

Impossibile testare, ma il generatore può essere configurato, secondo Marc-André Lafortune here. Quindi questo potrebbe funzionare:

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

Potrebbe funzionare, ma sembra terribilmente inefficiente. In linea di principio, dovresti solo trasmettere il valore generato più di recente da un computer all'altro; non dovresti serializzare l'intero oggetto. –

+1

Stai supponendo che non ci siano altri stati interni. Potresti sicuramente scrivere un generatore di numeri casuali per il quale è vero (modo più semplice: continua a ripetere l'istanza di Random con il numero precedente come valore di seed e usa solo la prima chiamata) ma non è proprio corretto dire che la classe Random corrente " dovrebbe in linea di principio "mantenere l'apolidia a causa di un caso d'uso raro". – SFEley