lua随机数的问题

简介: 在看 lua 的 math.random 函数的时候发现一个问题,就是在没有重新设置随机种子的时候, random 返回的前几个随机数并不是那么特别随机,尤其当随机范围很小的时候,比如 100 左右的时候基本上都是返回 1 ,看了源码后发现内部调用是( lua5.1 源码): lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; 这其实是生成了一个 0~1 之间的小数,然后根据 math.random 的参数个数来进行操作: 无参数时直接返回这个数,当然,会进行截断。

在看 lua 的 math.random 函数的时候发现一个问题,就是在没有重新设置随机种子的时候, random 返回的前几个随机数并不是那么特别随机,尤其当随机范围很小的时候,比如 100 左右的时候基本上都是返回 1 ,看了源码后发现内部调用是( lua5.1 源码):

lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;

这其实是生成了一个 0~1 之间的小数,然后根据 math.random 的参数个数来进行操作:

无参数时直接返回这个数,当然,会进行截断。

有一个参数时,计算 floor(r*u)+1 并返回,换句话说就是用这个小数跟唯一的上限相成下取整后 +1 返回。

有两个参数时:计算 floor(r*(u-l+1))+l 并返回,意思类似。

我们知道在 C语言 里如果在 rand()之前不进行 srand() 设置随机种子,那么 rand() 返回的序列是一定的,比如我的机器上 rand() 返回的第一个值就一直是 41.所以如果不对 lua 设置种子,而直接进行随机的时候会导致在给出的唯一上限比较小时,首个值是可以确定的,举例来说

math.random(100)

这个结果基本是就是 1,因为之前没有设置过种子,根据上面的生成过程,如果我机器上 rand() 还是返回 41,那么 r 将非常的小,所以返回的第一个值将等于 1,只要当我想要随机的范围非常大时才有可能摆脱这种情况,同时你也从此会发现,在这种情况下,无论你是 math.random(99) 还是 math.random(101) 结果都将为 1,原因如上

对于这种情况,lua-user 里给出的解决方案是在随机之前设置一下种子,并抛去前三个随机数,为什么是 3 个而不是 4 个,我也不知道为什么。。。。。。

同时把什么作为种子也是一个问题,一般对于随机性要求不高的系统来说,通常可以把系统时间作为种子,于是我们可以这么写:

math.randomseed( os.time() )
math.random(); math.random(); math.random()

但是这里还有一个问题,就是 os.time() 在短时间内变化非常小,系统时间按秒来递增,一段时间内变化的只是最低几位,如果你把这段代码运行起来就会发现,如果你运行程序的时间间隔不大的时候,随机数是没有变化的,对此 lua-user 也给出了方案:

math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) )

意思就是这个 os.time() 的数不是按秒变化吗?那就把它反过来,这样只要秒有变动,整个数就变动非常大,后面取了前 6 位,应该是种子的变化级别到了 10的5次方后应该就非常明显了,不需要更大的种子了。

但是这里还有一个问题,正是因为他截取了前 6 位,所以经过一段比较长的时间后这里的种子有可能又开始重复了,但是基于这种情况发生的概率比较小,而且即使发生重复,整体看起来应该也不影响随机性,所以可以接受。

详情见:http://lua-users.org/wiki/MathLibraryTutorial

倾城之链 | NICE LINKS DJI Mavic Air
目录
相关文章
|
IDE Java 程序员
请介绍一下 Python 中的泛型。
【2月更文挑战第16天】【2月更文挑战第48篇】
548 5
|
7月前
|
人工智能 监控 API
AI自动盯盘自由!OpenClaw 股票监控Skill实战(阿里云/本地部署+行情实时查询+避坑指南)
2026年,AI智能体已经深度融入日常投资与资产管理场景,OpenClaw(Clawdbot)凭借高度灵活的技能扩展机制,成为普通投资者实现自动化盯盘的首选工具。对于日常忙于工作、没有时间时刻盯盘的用户来说,能够让AI自动监控股票行情、实时反馈涨跌数据、动态管理自选股,已经成为刚需。Stock Watcher 作为 OpenClaw 生态中使用率极高的股票监控技能,可以直接对接实时行情源,支持沪深A股、科创板行情查询、自选股管理、涨跌提醒、走势总结,让你的 OpenClaw 从普通聊天助手,秒变24小时在线的股市观察员。
6352 5
|
人工智能 搜索推荐 前端开发
从代码到心灵对话:我的CodeBuddy升级体验之旅(个性化推荐微服务系统)
本文分享了使用CodeBuddy最新版本的深度体验,重点探讨了Craft智能体、MCP协议和DeepSeek V3三大功能。Craft实现从对话到代码的无缝转化,大幅提升开发效率;MCP协议打通全流程开发,促进团队协作;DeepSeek V3则将代码补全提升至新境界,显著减少Bug并优化跨语言开发。这些功能共同塑造了AI与程序员共生的未来模式,让编程更高效、自然。
1296 15
|
10月前
|
Linux C++ iOS开发
C++ SDL库入门指南(从零开始学习SDL2图形与游戏开发)
本教程来源https://www.vpshk.cn/带你使用C++和SDL2从零开始创建图形窗口,涵盖环境搭建、代码解析与编译运行,适合入门游戏开发与多媒体应用,轻松掌握跨平台图形编程基础。
|
域名解析 网络协议 数据安全/隐私保护
docker search 超时
docker search超时问题
2665 14
docker search 超时
|
存储 SQL 人工智能
DeepSeek开源周第五弹之二!Smallpond:构建于3FS之上的轻量级数据处理框架,高效处理PB级数据
Smallpond 是 DeepSeek 开源的轻量级数据处理框架,基于 DuckDB 和 3FS 构建,支持 PB 级数据处理,提供高性能的数据加载、查询和转换功能,适合大规模数据预处理和实时分析。
1369 1
DeepSeek开源周第五弹之二!Smallpond:构建于3FS之上的轻量级数据处理框架,高效处理PB级数据
|
JavaScript Ubuntu Java
零基础开发 nginx 模块
推荐学习资料: * nginx 开发指南: http://nginx.org/en/docs/dev/development_guide.html * nginx 动态模块编译博客文章: https://www.nginx.com/blog/compiling-dynamic-modules-nginx-plus/ * nginx 源码: https://github.com/nginx
5433 1
|
应用服务中间件 Linux 网络安全
nginx安装的详细教程(包括命令行安装和编译安装)
nginx安装的详细教程(包括命令行安装和编译安装)
|
SQL 存储 安全
Java安全编码:防范常见漏洞和攻击
【4月更文挑战第18天】本文介绍了Java安全编码的最佳实践,包括防止SQL注入和XSS攻击,使用预处理语句和转义用户输入。强调了安全的密码存储、角色基础的访问控制以及防止会话劫持和CSRF攻击。此外,还提到数据保护措施,如使用HTTPS和加密敏感数据。最后,建议避免在错误处理中泄露敏感信息并记录审计日志,以提升Java应用的安全性。
1015 4