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
}
相關文章
相關標籤/搜索