25

我正在用 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()),这使得随机数分布不再均匀。我的目标是能够重新运行上述程序并每次都收到一个随机选择的数字。

4

4 回答 4

23

您需要在使用之前运行math.randomseed() 一次math.random(),如下所示:

math.randomseed(os.time())

从您看到的第一个数字仍然相同的评论。这是由某些平台中随机生成器的实现引起的。

解决方案是在真正使用它们之前弹出一些随机数:

math.randomseed(os.time())
math.random(); math.random(); math.random()

请注意,标准 C 库random()通常不是那么均匀随机,如果您的平台提供更好的随机生成器,更好的解决方案是使用更好的随机生成器。

参考:Lua 数学库

于 2013-11-23T02:09:40.847 回答
13

Lua 中使用的标准 C 随机数生成器并不能保证对模拟有好处。“马尔可夫链”一词表明您可能需要一个更好的链。这是一个广泛用于蒙特卡罗计算的生成器:

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 的乘法随机数生成器,原始 Pascal 代码由http://osmf.sscc.ru/~smp/提供)

于 2013-11-24T17:20:39.877 回答
10
math.randomseed(os.clock()*100000000000)
for i=1,3 do
    math.random(10000, 65000)
end

总是产生新的随机数。更改种子值将确保随机性。不要跟随os.time(),因为它是纪元时间并且在一秒钟后发生变化,但os.clock()在任何关闭实例中都不会具有相同的值。

于 2015-09-02T12:30:32.833 回答
1

有 Luaossl 库解决方案:(https://github.com/wahern/luaossl

local rand = require "openssl.rand"
local randominteger
if rand.ready() then -- rand has been properly seeded
    -- Returns a cryptographically strong uniform random integer in the interval [0, n−1].
    randominteger = rand.uniform(99) + 1 -- randomizes an integer from range 1 to 100
end

http://25thandclement.com/~william/projects/luaossl.pdf

于 2020-05-20T01:35:21.990 回答