一、需求
目前存在一个需求,提供一个随机数的函数,这个函数的最小和最大值之间的精度是不等的,取他们中间的一个随机数,使用Lua自带的方法是做不到的,需要自己封装一个函数来使用。
二、解决
Lua本身的限制
Lua取随机数目前只有三种方式。
local result = math.random() -- 返回一个0 ~ 1之间的随机小数
local result = math.random(100) -- 返回1 ~ 100之间的随机整数
local result = math.random(10,100) -- 返回10 ~ 100之间的随机整数
解决思路
我先寻找了一下Lua有没有取数字精度的api,发现没有。那么就要首先搞到一个取精度的方式
本意并不想使用字符串来处理,但是想来想去也没有想到更加简便的处理方式了。如果有更加优雅的实现方式,也可以在评论区告诉我。
先搞了一个分割字符串的函数,然后把数字转化成字符串用字符’.’(小数点)来分割。这样取到的表[2]一定是小数部分。没有取到[2]就说明这是一个整数。
接下来要以精度最高的数作为基准数字来处理。因为Lua取随机小数只有math.random(),并且范围是0~1,所以可以使用max和min之间的差值乘上这个值即可取得随机值,这个值再加上min就是想要获得的随机值。
但是这时候会出现一个问题,就是精度问题。math.random()取到的数精度很高,我在代码里对精度进行了取余然后四舍五入的运算,这样可以保证小数点精度一致性。
最终获得的值,经过一定测试后简单的认为分布比较均匀。
测试结果
(这水印也太挡视野了)
缺陷
性能问题
字符串处理性能应该是不好的,如果有更好的方式可以告诉我。
最终代码
-- 分割字符串
local function split(input, delimiter)
input = tostring(input)
delimiter = tostring(delimiter)
if delimiter == '' then
return false
end
local pos,arr = 0, {}
for st,sp in
function()
return string.find(input, delimiter, pos, true)
end
do
table.insert(arr, string.sub(input, pos, st - 1))
pos = sp + 1
end
table.insert(arr, string.sub(input, pos))
return arr
end
-- 搞这个split有点耗费性能 但是暂时想不到更好的办法了……
local function any_random(min,max)
if max <= min then
return min
end
local tb_min = split(min,'.')
local tb_max = split(max,'.')
local accuracy_min,accuracy_max = 0,0
if tb_min[2] then
accuracy_min = string.len(tb_min[2])
end
if tb_max[2] then
accuracy_max = string.len(tb_max[2])
end
local final_accuracy = math.max(accuracy_min,accuracy_max)
-- 说明都是整数
if final_accuracy == 0 then
return math.random(min,max)
end
local rate = math.random()
local final_random = (max - min) * rate + min
-- 四舍五入,这个值必定等于 传入参数的最高精度的1/0 例如 1.1,1.334 那么他一定是0.001/0.000
local round = math.floor(((final_random % (0.1 ^ final_accuracy)) * (10 ^ final_accuracy) + 0.5)) * (0.1 ^ final_accuracy)
local result = final_random - final_random % (0.1 ^ final_accuracy) + round
local temp = 10 ^ final_accuracy
result = math.floor(result * temp) / temp
return result
end
版权声明:本文为OvejeJ1原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。