zoukankan      html  css  js  c++  java
  • openresty及lua的随机函数

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

    所以,当我们没有初始化的时候,如果直接使用math.random(),那么出来的值肯定是每次都一样,因为种子等于0。

    因此,我们都会在进程启动前,我们先调用一下种子

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

    但是,这一切在operensty的多进程里面被打破了,因为随机以后的因子。。各个进程不共享。。

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

    好吧,除非将随机因子放入共享内存,并且自己实现随机算法,不然的话。。math.random是废了!

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

    以下文档摘自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
    }
  • 相关阅读:
    LeetCode153 Find Minimum in Rotated Sorted Array. LeetCode162 Find Peak Element
    LeetCode208 Implement Trie (Prefix Tree). LeetCode211 Add and Search Word
    LeetCode172 Factorial Trailing Zeroes. LeetCode258 Add Digits. LeetCode268 Missing Number
    LeetCode191 Number of 1 Bits. LeetCode231 Power of Two. LeetCode342 Power of Four
    LeetCode225 Implement Stack using Queues
    LeetCode150 Evaluate Reverse Polish Notation
    LeetCode125 Valid Palindrome
    LeetCode128 Longest Consecutive Sequence
    LeetCode124 Binary Tree Maximum Path Sum
    LeetCode123 Best Time to Buy and Sell Stock III
  • 原文地址:https://www.cnblogs.com/linbc/p/10555623.html
Copyright © 2011-2022 走看看