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
    }
  • 相关阅读:
    Java转Exe
    匹配数字和字母的正则表达式
    POI
    Maven– HelloWorld实例
    eclipse+maven+tomcat构建web工程
    Maven
    SSH
    Struct2小结:
    Eclipse中没有javax.servlet和javax.servlet.http包的处理办法
    openSession()与getCurrentSession()的区别
  • 原文地址:https://www.cnblogs.com/linbc/p/10555623.html
Copyright © 2011-2022 走看看