一次生活引发的“Lua随机数生成”问题

来源:互联网 发布:昆仑虚手游刷元宝软件 编辑:程序博客网 时间:2024/05/17 16:01

Preface

其实是打算写个随机性语言选择器的。我和小伙伴打算每天换一门语言来对话,于是就采用随机函数的方法去帮助我们去选择!这次比较匆忙,脚本就暂且这样,以后优化,文章美化就暂时这样,以后再调整。
这个随机数生成问题目前主要是分成4个部分。最常见的,一次改进的,二次改进的和三次改进。以下主要改进的是randomseed的取值~

程序1:初始的最常见的随机数生成

-- 常见的随机数生成math.randomseed(os.time())for i=1, 7 do    print(math.random())end  

一次改进

改进的核心:
可以查看这篇文章,里面有说明random()的 seed 很小或者seed 变化很小,产生的随机序列仍然很相似。Lua 随机数生成问题,点我

核心的语句如下:

-- 该语句是作用是:将os.time()的结果反转,然后取高6位,这样seed的变化就大了,math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 6)))

以下是用来帮助选择语言的实例代码:

-- 全局变量,在这里控制概率的大小English = 13Cantonese = 7Japanese = 8Korean = 67-- 随机函数function rnd()    local ret = 0        -- 基于系统时间的随机数种子,用这种方式防止极端时间内造成随机数相同的情况        -- 事实上,这个还是不行,最多只是减轻症状,后文再细说)    math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 6)))    -- 因为这个随机函数有点不好,所以取第三个信任度比较高    for i=1, 3 do        n = math.random(1, 10001)        ret = n    end    return retend-- 对于随机函数粗来的结果进行处理,通过取余来决定哪种语言while true do    local number = rnd()    if number % Cantonese == 0 then        print("随机数为:"..number)        print("粤语")        break    elseif number % English == 0 then        print("随机数为:"..number)        print("English")        break    elseif number % Japanese == 0 then        print("随机数为:"..number)        print("日本語")        break    --[[    elseif number % Korean == 0 then        print("随机数为:"..number)        print("한국어")        break    ]]    endend

这个程序还是有问题,时间紧迫,先放着!先去洗澡了
其实,这个问题还是没有解决~因为,经过测试发现,在Lua5.3里面(其他版本未经测试),在极其短的时间里面,生成的随机序列仍然相同~还是不能达到根本的要求。


二次改进:

-- 调用sockt库,从而达到毫秒级精度local socket = require("socket")math.randomseed(socket.gettime())while true do    for i=1, 3 do        n = math.random()    end    -- 依旧取第三个数,输出后发现差别可能随机数会有很多的差别    -- 说明:因为socket.gettime()得到的结果是0.xxxxxxxxx级别的,无法作为程序中的种子用,所以放大    print(math.floor(n * 1000001))end

输出结果样例:(部分)

944548
118388
148720

863934
417030
699109
202577
950752
172985
150584
111708

793783
48523
8192
721530
558812
807733
364529
57704
950531
737050
434112
866802
155902
336599
326696

722702
992281
477198
424833

842600
675044
40556
87856
680879
236654
454290
536366
433633
319076
343280

617953
936876

输出后,发现虽然这次差别度很大,变化相差很大,可以达到随机选择语言的需求了。但是对于,红色的标记的序列来说,差别没有达到理想中的状态(我不是处女座也不是双鱼座的!


三次改进

此次改进是基于第一次改进的理念改进的,将得到的序列进行逆序取高位,这样效果应该会好很多。代码如下:

local socket = require("socket")math.randomseed(socket.gettime())while true do    for i=1, 3 do        n = math.random()    end    print(tonumber(tostring(math.floor(n * 1000001)):reverse()))end

样例输出:

558083
7541
886742
27599
528329
444804
469048
986654
825257
47004
223707
696051
828321
270441
928724
265446
57508
754028
799111
724897
2945
326045
207465
184182
786509
170548
47116
888255
361378

这样就有个别几个没有连续重复的了~从统计学角度来说,有也是在允许范围的吧~(弄完这个,感觉可能没有必要!是的,感觉!其实,二次改进的蛮好的

最后,改进的实例代码如下:

-- 全局变量,在这里控制概率的大小English = 11Cantonese = 7Japanese = 8Korean = 67-- 随机函数function rnd()    local socket = require("socket")    local ret = 0    -- 用socket.gettime()获取更加精确的时间,math.floor()取其整数部分,省略小数部分    -- 转换成string,逆序    -- 再转换成number    local sockt_number = tonumber(tostring(math.floor(socket.gettime() * 1000001)):reverse())    math.randomseed(sockt_number)    -- 因为这个随机函数有点不好,所以取第三个信任度比较高    for i=1, 3 do        n = math.random(1, 10001)        ret = n    end    return retend-- 对于随机函数粗来的结果进行处理,通过取余来决定哪种语言while true do    local number = rnd()    print("随机数为:"..number)    if number % Cantonese == 0 then        print("粤语")        break    elseif number % English == 0 then        print("English")        break    elseif number % Japanese == 0 then        print("日本語")        break    --[[    elseif number % Korean == 0 then        print("한국어")        break    ]]    endend

改进前,因为while的永真循环,程序运行时间极其短暂,所以随机数取的是一样的,取余操作都是在做无用功。改进过后,随机数改进后的程序,就可以超快地得到结果。当然了,也可以对求余操作进行改进,更快地得到求余后的结果。

1 0
原创粉丝点击