Lua 4.0 随机数生成器
2013-9-10 8:20:18
收藏:0
阅读:210
评论:3
我在 Lua 4.0 中没有访问 random() 的权限(不要问我为什么),因此我需要自己编写一个随机数生成器。或者说,我必须再次编写另一个,因为我几年前实现的那个现在已经出问题了。即,我注意到了重复的值,这是不好的。
有没有用 Lua 编写的建议或示例可以供我使用?FYI,这是我到目前为止一直在使用的:
seedobja = 1103515245
seedobjc = 12345
seedobjm = 4294967295 --0x100000000
function srandom(seedobj, fVal1, fVal2)
seedobj[1] = mod(seedobj[1] * seedobja + seedobjc, seedobjm)
local temp_rand = seedobj[1] / (seedobjm - 1)
if (fVal2) then
return floor(fVal1 + 0.5 + temp_rand * (fVal2 - fVal1))
elseif (fVal1) then
return floor(temp_rand * fVal1) + 1
else
return temp_rand
end
end
点赞
用户2633423
这里是另一种尝试(仍然是Lua 5.1代码),使用Knuth的减法生成器的C语言适配(不是线性同余)。根据Knuth的说法,它应该能够使用FP算术(甚至是单精度)。
local mod = math.fmod
local floor = math.floor
local abs = math.abs
local B = 4000000
-- Knuth浮点数生成器的粗略适配
function srandom(seedobj, fVal1, fVal2)
local ma = seedobj.ma
local seed = seedobj.seed
local mj, mk
if seed < 0 or not ma then
ma = {}
seedobj.ma = ma
mj = abs(1618033 - abs(seed))
mj = mod(mj, B)
ma[55] = mj
mk = 1
for i = 1, 54 do
local ii = mod(21 * i, 55)
ma[ii] = mk
mk = mj - mk
if mk < 0 then mk = mk + B end
mj = ma[ii]
end
for k = 1, 4 do
for i = 1, 55 do
ma[i] = ma[i] - ma[1 + mod(i + 30, 55)]
if ma[i] < 0 then ma[i] = ma[i] + B end
end
end
seedobj.inext = 0
seedobj.inextp = 31
seedobj.seed = 1
end
local inext = seedobj.inext
local inextp = seedobj.inextp
inext = inext + 1
if inext == 56 then inext = 1 end
seedobj.inext = inext
inextp = inextp + 1
if inextp == 56 then inextp = 1 end
seedobj.inextp = inextp
mj = ma[inext] - ma[inextp]
if mj < 0 then mj = mj + B end
ma[inext] = mj
local temp_rand = mj / B
if fVal2 then
return floor(fVal1 + 0.5 + temp_rand * (fVal2 - fVal1))
elseif fVal1 then
return floor(temp_rand * fVal1) + 1
else
return temp_rand
end
end
-- 测试
-- 注意:seedobj必须是带有一个名为“seed”的字段的表;
-- 这个字段必须为负数;在生成第一个数字之后,seedobj表将被填充
-- 需要生成数字的附加状态;将其“seed”字段更改为负数将重新初始化
-- 生成器并开始一个新的伪随机序列。
local seedobj = {seed = -232343}
for i = 1, 100 do
print(srandom(seedobj, 100, 1000))
end
2013-09-10 17:35:27
用户330663
我在这里找到了一个解决方案 here:
function mul16(a, b)
local a_lo, b_lo = mod(a, 2^8), mod(b, 2^8)
local a_hi, b_hi = a - a_lo, b - b_lo
return mod(a_lo * b_lo + mod(a_lo * b_hi, 2^16) + mod(a_hi * b_lo, 2^16) + mod(a_hi * b_hi, 2^16), 2^16)
end
function lcg(s, r)
local temp = {}
function temp:random(a, b)
local y = mod(mul16(self.a, self.x) + self.c, self.m)
self.x = y
if not a then
return y / 65536
elseif not b then
if a == 0 then
return y
else
return 1 + mod(y, a)
end
else
return a + mod(y, b - a + 1)
end
end
function temp:randomseed(s)
if not s then
s = seed()
end
self.x = mod(s, 2147483648)
end
-- 'Numerical Recipes' parameters
temp.a = 26125
temp.c = 62303
temp.m = 65536
temp:randomseed(s)
return temp
end
local R = lcg(0974)
local rand_table = {}
for i = 1, 10000 do
local new_value = R:random()
rand_table[i] = new_value
if (i > 1) then
for j = 1, i - 1 do
local old_value = rand_table[j]
if (new_value == old_value) then
print("\ti = " .. i .. "\n\tj = " .. j .. "\n\tnew_value = " .. new_value .. "\n\told_value = " .. old_value)
break
end
end
end
end
我不知道其统计特性如何,但这个函数即使经过数千次迭代也没有返回重复值。无论如何,感谢所有人的帮助!
2013-09-11 13:59:49
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
我没有安装 Lua 4.0,也从未与它一起工作,因此以下代码可能需要一些调整。
这是Lua 5.1上的一些东西。它是Park和Miller生成器实现的一个粗略的适应(用C编写,使用32位整数)。我试图接近4.0的语法(从你的片断中猜测出来)。测试并查看其周期是否符合您的需求。原始版本约为2e9的周期,但转换为浮点运算可能会导致出现问题(这些生成器是娇嫩的东西)。
local mod = math.fmod local floor = math.floor local B = 2 ^ 31 -- 粗略适应Park-Miller生成器 function srandom(seedobj,fVal1,fVal2) local seed = seedobj [1] local k = mod(floor(seed / 127773),B) seed = mod(16807 *(seed-mod(k * 127773,B)),B) seed = seed - mod(2836 * k,B) if seed <0 then seed = mod(seed + B-1,B)end seedobj [1] =种子 local temp_rand =种子/(B-1) if fVal2 then 返回floor(fVal1 + 0.5 + temp_rand *(fVal2-fVal1)) elseif fVal1 then 返回floor(temp_rand * fVal1)+1 否则 返回temp_rand end end -- 测试 local seedobj = {2} //第一个元素是种子,不得为0 对于i = 1,100做 print(srandom(seedobj,100,1000)) end