Создание однородных случайных чисел в Lua
Я работаю над программированием цепи Маркова в Lua, и один элемент этого требует, чтобы я равномерно генерировал случайные числа. Вот упрощенный пример, иллюстрирующий мой вопрос:
example = function(x)
local r = math.random(1,10)
print(r)
return x[r]
end
exampleArray = {"a","b","c","d","e","f","g","h","i","j"}
print(example(exampleArray))
Моя проблема в том, что, когда я повторно запускаю эту программу несколько раз (mash F5), создается то же самое случайное число, в результате чего функция выбора выбирает тот же самый элемент массива. Тем не менее, если я включаю много вызовов в примерную функцию внутри одной программы, повторяя линию печати в конце много раз, я получаю подходящие случайные результаты.
Это не мое намерение, поскольку надлежащий марковский псевдослучайный текстовый генератор должен иметь возможность запускать одну и ту же программу с одними и теми же входами несколько раз и каждый раз выводить различный псевдослучайный текст. Я попытался сбросить семя с помощью math.randomseed(os.time())
, и это делает так, что распределение случайных чисел больше не равномерное. Моя цель состоит в том, чтобы иметь возможность повторно запускать указанную выше программу и получать случайно выбранный номер каждый раз.
Ответы
Ответ 1
Перед использованием math.random()
нужно выполнить math.randomseed()
один раз, например:
math.randomseed(os.time())
Из вашего комментария, что вы видели первый номер, все тот же. Это вызвано реализацией случайного генератора на некоторых платформах.
Решение состоит в том, чтобы поместить некоторые случайные числа, прежде чем использовать их для реального:
math.randomseed(os.time())
math.random(); math.random(); math.random()
Обратите внимание, что стандартная библиотека C random()
обычно не является настолько однородной случайной, лучшее решение - использовать лучший случайный генератор, если ваша платформа обеспечивает его.
Ссылка: Библиотека Lua Math
Ответ 2
Генератор случайных чисел стандарта C, используемый в Lua, не является подходящим для моделирования. Слова "цепь Маркова" предполагают, что вам может понадобиться лучшая. Здесь генератор, широко используемый для расчетов Монте-Карло:
local A1, A2 = 727595, 798405 -- 5^17=D20*A1+A2
local D20, D40 = 1048576, 1099511627776 -- 2^20, 2^40
local X1, X2 = 0, 1
function rand()
local U = X2*A2
local V = (X1*A2 + X2*A1) % D20
V = (V*D20 + U) % D40
X1 = math.floor(V/D20)
X2 = V - X1*D20
return V/D40
end
Он генерирует число от 0 до 1, поэтому r = math.floor(rand()*10) + 1
войдет в ваш пример.
(Этот мультипликативный генератор случайных чисел с периодом 2 ^ 38, множитель 5 ^ 17 и по модулю 2 ^ 40, исходный код Паскаля http://osmf.sscc.ru/~smp/)
Ответ 3
math.randomseed(os.clock()*100000000000)
for i=1,3 do
math.random(10000, 65000)
end
Всегда приводит к новому случайному числу. Изменение начального значения обеспечит случайность, Dont не следует os.time()
потому что его время эпохи и изменяется через одну секунду, но os.clock()
не имеет одинакового значения в любом близком экземпляре. Ура!