Создание однородных случайных чисел в 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() не имеет одинакового значения в любом близком экземпляре. Ура!