Generating uniform random numbers in Lua
我正在用Lua编写Markov链,而其中的一个元素要求我统一生成随机数。 这是一个简化的例子来说明我的问题:
1 2 3 4 5 6 7 8 9 | 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伪随机文本生成器应该能够以相同的输入多次运行相同的程序,并且每次都能输出不同的伪随机文本。 我尝试使用
使用
1 | math.randomseed(os.time()) |
从您的评论中,您看到第一个数字仍然相同。这是由某些平台上随机生成器的实现引起的。
解决方案是先弹出一些随机数,然后再将它们用于实数:
1 2 | math.randomseed(os.time()) math.random(); math.random(); math.random() |
请注意,标准C库
参考:Lua数学库
Lua中使用的标准C随机数生成器并不能很好地模拟。"马尔可夫链"一词表明您可能需要更好的一个。这是广泛用于蒙特卡洛计算的生成器:
1 2 3 4 5 6 7 8 9 10 11 | 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之间的数字,因此
(那是周期为2 ^ 38,乘数5 ^ 17和模2 ^ 40的乘法随机数生成器,原始Pascal代码是http://osmf.sscc.ru/~smp/)
1 2 3 4 | math.randomseed(os.clock()*100000000000) for i=1,3 do math.random(10000, 65000) end |
总是产生新的随机数。更改种子值将确保随机性,不要跟随
有Luaossl库解决方案:(https://github.com/wahern/luaossl)
1 2 3 4 5 6 | 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