2010-08-27 5 views
5

Класс Random в Ruby 1.9.2 гарантированно генерирует случайные числа в том же порядке, что и для конкретного семени и диапазона. Например:Генерация распределенных последовательных случайных чисел в Ruby 1.9.2

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

Но предположим, что я хочу, чтобы генерировать следующий номер в последовательности на другом компьютере (без повторной генерации ранее чисел в последовательности). Это должно быть возможным, учитывая предыдущий результат. Есть ли способ сделать это с классом Random? Или мне нужно написать собственную реализацию Mersenne twister?

[Редактировать: Как указано в комментариях ниже, это на самом деле не возможно определить состояние Random экземпляра только с выхода, потому что только часть состояния (в частности, низкий 32 бит) используются для выхода.]

+0

Почему это возможно? – adamse

+0

@adamse Следующее число генерируется детерминированным образом с учетом некоторого внутреннего состояния в 'r'. Поэтому, если вы создадите новый 'r' с тем же состоянием, что и старый, он будет генерировать следующее число в последовательности. Имеет смысл? Основываясь на моем понимании алгоритмов, лежащих в основе «Случайного», я считаю, что это состояние может быть представлено семенем и последним сгенерированным числом. –

+0

, прочитав реализацию [backported] (http://github.com/marcandre/backports/blob/master/lib/backports/1.9.2/random/MT19937.rb), кажется, что вы можете найти следующее состояние, используя последний и семя. Однако, насколько я понимаю, вы, возможно, не сможете найти состояние, заданное сгенерированным числом. – adamse

ответ

2

Невозможно проверить, но генератор может быть выведен из строя, согласно Marc-André Lafortune here. Это может сработать:

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

Это может сработать, но это кажется ужасно неэффективным. В принципе, вам нужно всего лишь передать самое последнее сгенерированное значение с одного компьютера на другой; вам не нужно сериализовать весь объект. –

+1

Вы делаете предположение, что нет другого внутреннего состояния. Вы могли бы, конечно, написать генератор случайных чисел, для которого это правда (самый простой способ: сохранить повторное создание Random с предыдущим номером в качестве начального значения и использовать только первый вызов), но не совсем справедливо сказать, что текущий класс Random " должен в принципе «поддерживать безгражданство ради необычного случая использования». – SFEley