我正在编写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 ),会生成完全相同的随机数,从而导致示例函数选择完全相同的数组元素。但是,如果我通过在末尾多次重复打印行多次调用单个程序中的示例函数,我会得到合适的随机结果。
这不是我的意图,因为正确的Markov伪随机文本生成器应该能够多次运行具有相同输入的相同程序,并且每次都输出不同的伪随机文本。我已经尝试使用math.randomseed(os.time())
重置种子,这使得随机数分布不再一致。我的目标是能够重新运行上述程序,并且每次都会收到一个随机选择的号码。
答案 0 :(得分:11)
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/)
答案 1 :(得分:10)
在使用math.randomseed()
之前,您需要先运行math.random()
,如下所示:
math.randomseed(os.time())
根据您的评论,您看到第一个号码仍然相同。这是由某些平台上随机生成器的实现引起的。
解决方案是在使用它们之前弹出一些随机数:
math.randomseed(os.time())
math.random(); math.random(); math.random()
请注意,标准C库random()
通常不是那么均匀随机,更好的解决方案是使用更好的随机生成器,如果您的平台提供一个。
答案 2 :(得分:5)
math.randomseed(os.clock()*100000000000)
for i=1,3 do
math.random(10000, 65000)
end
始终会产生新的随机数。更改种子值将确保随机性,不要跟随os.time()
因为它的纪元时间并且在一秒之后发生变化,但os.clock()
在任何近距离实例上都没有相同的值。干杯!
答案 3 :(得分:0)
有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