在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))

我的问题是,当我多次重新运行这个程序(连续按 F5)时,会生成完全相同的随机数,导致例子函数选择完全相同的数组元素。然而,如果我在单个程序中多次调用示例函数,通过重复执行末尾的打印行,我会得到合适的随机结果。

这不是我的意图,因为一个合适的马尔可夫伪随机文本生成器应该能够多次运行相同的程序以相同的输入,并在每次输出不同的伪随机文本。我尝试使用 math.randomseed(os.time()) 重置种子,这样随机数发生器的分布不再是均匀的。我的目标是能够重新运行上面的程序,并每次都收到随机选择的数字。

点赞
用户1009479
用户1009479

你需要在使用 math.random() 之前仅需一次运行 math.randomseed(),就像这样:

math.randomseed(os.time())

从你的评论中得知,你看到的第一个数字仍然是相同的。这是由于某些平台在随机生成器的实现方式上引起的。

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

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

请注意,标准 C 库的 random() 通常不是如此均匀的随机数,如果您的平台提供更好的随机生成器,则可以使用更好的随机生成器。

参考:Lua 数学库教程

2013-11-23 02:09:40
用户1365066
用户1365066

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-24 17:20:39
用户3982519
用户3982519
math.randomseed(os.clock()*100000000000)  // 设置随机数种子
for i=1,3 do  // 生成三个随机数
    math.random(10000, 65000)  // 随机生成 10000-65000 之间的数
end

总是产生新的随机数。改变种子值可以保证随机性。不要使用os.time(),因为它是时代时间,在一秒钟后会变化,但os.clock()不会在任何接近的实例中具有相同的值。

2015-09-02 12:30:32
用户13578722
用户13578722

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

local rand = require "openssl.rand"
local randominteger
if rand.ready() then -- rand 已经被适当地种子化
    -- 在区间 [0,n-1] 中返回一个加密强度的均匀随机整数。
    randominteger = rand.uniform(99) + 1 -- 从 1 到 100 的范围随机生成一个整数
end

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

2020-05-20 01:35:21