openresty及lua的随机函数

咱们都知道,所谓的随机都是伪随机,随机的结果是由随机算法和随机种子决定的。算法

因此,当咱们没有初始化的时候,若是直接使用math.random(),那么出来的值确定是每次都同样,由于种子等于0。缓存

所以,咱们都会在进程启动前,咱们先调用一下种子dom

--随机种子初始化
math.randomseed(tostring(os.time()):reverse():sub(1, 6))函数

可是,这一切在operensty的多进程里面被打破了,由于随机之后的因子。。各个进程不共享。。this

若是,有2个进程,那么意味着,一样的值会出现两遍,好比在游戏里面开宝箱,很容易被玩家抓到规律。spa

好吧,除非将随机因子放入共享内存,而且本身实现随机算法,否则的话。。math.random是废了!code

好了,不须要随机种子的随机方法,我想起了。。/dev/randomblog

如下文档摘自https://zh.wikipedia.org/wiki//dev/random游戏

因为不可抗拒缘由,你们能够看看截图进程

咱们只要知道这样的随机方式,不可预测的真随机,来自硬件的因子,而且记得

  • /dev/random是阻塞的
  • /dev/urandom是非阻塞的

那么,对咱们而言/dev/urandom是够的,因此。。我仍是把代码贴一下就行了

local MAX_UINT = math.pow(2,32)

--因为随机函数是很是频繁的,因此,仍是作了一个随机池在那边,先随机一大部分放着
local cache_results = {}
local cache_index = 0

local table_getn = table.getn

--种子不须要初始化了
local function init()
end

--从系统随机文件中读取
local function urandom()
    --看下缓存里面还有没有
    local this_count = table_getn(cache_results) - cache_index
    if this_count <= 0 then
        --每次读取128个整数,512个字节缓存下来
        local COUNT = 1024
        local frandom = assert(io.open("/dev/urandom", "rb"))
        local s = frandom:read(4 * COUNT)
        assert(s:len() == 4 * COUNT)

        for i=1,COUNT do
            --读取4个字节做为一个整数
            local v = 0
            for c = 1, 4 do
                v = 256 * v + s:byte(i*c)
            end
            cache_results[i] = v
        end
        io.close(frandom)

        --从新把
        this_count = table_getn(cache_results)
        cache_index = 0
    end

    cache_index = cache_index + 1
    return cache_results[cache_index]
end

local rand = urandom

--随机一个0-1之间的浮点数
local function randFloat()
    return rand()/(MAX_UINT+1)
end

--随机给定范围[a,b]的整数
local function randInt(a, b)
    assert(b >= a)
    local v = rand()
    return a + math.floor((b-a+1)*randFloat())
end

return {
    init = init,
    rand = rand,
    urandom = urandom,
    randInt = randInt,
    randFloat = randFloat
}
相关文章
相关标签/搜索