跳转至

随机数(random)

一、随机数概述

随机数是专门的随机试验的结果. 在统计学的不同技术中需要使用随机数,比如在从统计总体中抽取有代表性的样本的时候,或者在将实验动物分配到不同的试验组的过程中,或者在进行蒙特卡罗模拟法计算的时候等等. 产生随机数有多种不同的方法.这些方法被称为随机数生成器.随机数最重要的特性是它在产生时后面的那个数与前面的那个数毫无关系.

根据密码学原理,随机数的随机性检验可以分为三个标准:

1.统计学伪随机性.统计学伪随机性指的是在给定的随机比特流样本中,1的数量大致等于0的数量,同理,“10”“01”“00”“11”四者数量大致相等.类似的标准被称为统计学随机性.满足这类要求的数字在人类“一眼看上去”是随机的.

2.密码学安全伪随机性.其定义为,给定随机样本的一部分和随机算法,不能有效的演算出随机样本的剩余部分.

3.真随机性.其定义为随机样本不可重现.实际上只要给定边界条件,真随机数并不存在,可是如果产生一个真随机数样本的边界条件十分复杂且难以捕捉(比如计算机当地的本底辐射波动值),可以认为用这个方法演算出来了真随机数.

相应的,随机数也分为三类:

1.伪随机数:满足第一个条件的随机数.

2.密码学安全的伪随机数:同时满足前两个条件的随机数.可以通过密码学安全伪随机数生成器计算得出.

3.真随机数:同时满足三个条件的随机数.

我们知道,随机数是通过一些复杂的数学算法得到的,那么 随机种子就是这些随机数的初始值.

一般计算机里面产生的随机数都是伪随机数. 伪随机数,也是就一个一直不变的数,所以我们可以通过输入随机种子得到一个初始固定的随机数.

例如,随机数的种子设置为x,产生的随机数序列为: [123, 456,789,...],那么只要输入相同的随机种子x,就能得到相同的随机数序列:[123, 456,789,...],否则就无法还原出随机数序列,也就无法通过密码学安全的随机数生成器计算出随机数序列.

二、演示功能概述

本文章通过 Air780 的核心板烧录底层固件(LuatOS-SoC_V2002_Air780EP)和修改 LuatOS 示例代码(点此链接查看 crypto 的 demo 例子),来演示有关随机数的各种 API 的功能.

三、硬件准备

参考:硬件环境清单第二章节内容,准备以及组装好硬件环境。

四、软件环境

“凡事预则立,不预则废。”在详细阐述本功能示例之前,我们需先精心筹备好以下软件环境。

1. Luatools工具

2. 内核固件文件(底层core固件文件):LuatOS-SoC_V2002_Air780EP;参考项目使用的内核固件

3. luatos需要的脚本和资源文件

脚本和资源文件点击此处查看与下载

lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件;

准备好软件环境之后,接下来查看如何烧录项目文件到Air780EP核心板,将本篇文章中演示使用的项目文件烧录到Air780EP核心板中。

五、API 说明

5.1 crypto.trng(len)

生成真随机数

参数

传入值类型
解释
int
数据长度

返回值

返回值类型
解释
string
指定随机数字符串

例子

-- 生成 32 位随机数 ir

local r = crypto.trng(4)

local _, ir = pack.unpack(r, "I")


5.2 math.random([n [,m]])

生成伪随机数

参数

传入值类型
解释
int
生成随机数范围
int
生成随机数范围

返回值

返回值类型
解释
local
随机数字

例子

--无参调用,产生[0, 1)之间的浮点随机数.

local num = math.random()

--一个参数 n,产生[1, n]之间的整数

local num = math.random(n)

--两个参数,产生[n, m]之间的整数.

local num = math.random(n,m)


5.3 math.randomseed(n)

用法:设置一个整数 n 作为随机序列的种子.

参数

传入值类型
解释
int
种子数据

返回值

例子

--得到了正常的随机数

math.randomseed(os.time())

for i=0, 10 do

  local n = math.random(10)

end

--一系列相同的数,这种在一个 for 循环内设置随机数的写法 seed 几乎是一样导致.

for i=0, 10 do

  math.randomseed(os.time())

  local n = math.random(10)

end

六、功能演示

6.1 修改示例

首先找到 LuatOS-Air780EP-master\demo\crypto\main.lua 脚本文件,复制一份 main.lua 文件到任意目录,我复制到 D:\Desktop\LuatOS-Air780EP-master\random 这个目录

然后修改代码:

PROJECT = "cryptodemo"
VERSION = "1.0.0"
-- sys库是标配
_G.sys = require("sys")

sys.taskInit(function()

    sys.wait(1000)
    -- ---------------------------------------
    log.info("随机数测试")
    math.randomseed(os.time())
    for i=1, 10 do
         sys.wait(100)
         log.info("crypto", "真随机数",string.unpack("I",crypto.trng(4)))
         log.info("crypto", "伪随机数",math.random()) -- 输出的是浮点数,不推荐
         log.info("crypto", "伪随机数",math.random(100)) --输出1-100之间随机数
         log.info("crypto", "伪随机数",math.random(1, 65525)) -- 不推荐
    end
    log.info("crypto", "ALL Done")
    sys.wait(100000)
end)

sys.run()

对应 Log

[2024-10-18 15:30:52.567] 工具提示: soc log port COM5打开成功
[2024-10-18 15:30:52.595] 工具提示: ap log port COM6打开成功
[2024-10-18 15:30:52.598] 工具提示: 用户虚拟串口 COM9
[2024-10-18 15:30:52.677] 工具提示: 用户log保存在D:\Desktop\LuaTools\log\trace_2024-10-18_153052.txt 如果有问题交给FAE
[2024-10-18 15:30:52.676][000000000.009] am_service_init 851:Air780EP_A17
[2024-10-18 15:30:52.686][000000000.023] Uart_BaseInitEx 1049:uart 0 rx cache 256 dma 256
[2024-10-18 15:30:52.687][000000000.225] self_info 122:model Air780EP_A17 imei 868327075469021
[2024-10-18 15:30:52.688][000000000.227] I/pm poweron: Power/Reset
[2024-10-18 15:30:52.689][000000000.227] I/main LuatOS@EC618 base 23.11 bsp V1112 32bit
[2024-10-18 15:30:52.690][000000000.227] I/main ROM Build: Sep  3 2024 15:55:27
[2024-10-18 15:30:52.691][000000000.235] D/main loadlibs luavm 262136 14360 14392
[2024-10-18 15:30:52.692][000000000.235] D/main loadlibs sys   277872 53984 81264
[2024-10-18 15:30:52.694][000000000.246] I/user.main        cryptodemo        1.0.0
[2024-10-18 15:30:53.486][000000001.276] I/user.随机数测试
[2024-10-18 15:30:53.596][000000001.386] I/user.crypto        真随机数        -2126957010        5
[2024-10-18 15:30:53.607][000000001.388] I/user.crypto        伪随机数        0.4636298
[2024-10-18 15:30:53.611][000000001.389] I/user.crypto        伪随机数        50
[2024-10-18 15:30:53.613][000000001.390] I/user.crypto        伪随机数        46998
[2024-10-18 15:30:53.690][000000001.491] I/user.crypto        真随机数        -309051301        5
[2024-10-18 15:30:53.693][000000001.492] I/user.crypto        伪随机数        0.6394390
[2024-10-18 15:30:53.706][000000001.501] I/user.crypto        伪随机数        10
[2024-10-18 15:30:53.714][000000001.502] I/user.crypto        伪随机数        38883
[2024-10-18 15:30:53.802][000000001.604] I/user.crypto        真随机数        -1863938574        5
[2024-10-18 15:30:53.805][000000001.605] I/user.crypto        伪随机数        0.9536643
[2024-10-18 15:30:53.807][000000001.607] I/user.crypto        伪随机数        25
[2024-10-18 15:30:53.811][000000001.608] I/user.crypto        伪随机数        16512
[2024-10-18 15:30:53.928][000000001.717] I/user.crypto        真随机数        1261760763        5
[2024-10-18 15:30:53.934][000000001.719] I/user.crypto        伪随机数        0.6245894
[2024-10-18 15:30:53.937][000000001.720] I/user.crypto        伪随机数        54
[2024-10-18 15:30:53.940][000000001.721] I/user.crypto        伪随机数        21478
[2024-10-18 15:30:54.023][000000001.822] I/user.crypto        真随机数        936401639        5
[2024-10-18 15:30:54.027][000000001.824] I/user.crypto        伪随机数        0.9050973
[2024-10-18 15:30:54.036][000000001.833] I/user.crypto        伪随机数        1
[2024-10-18 15:30:54.039][000000001.834] I/user.crypto        伪随机数        44043
[2024-10-18 15:30:54.148][000000001.936] I/user.crypto        真随机数        1715074597        5
[2024-10-18 15:30:54.156][000000001.937] I/user.crypto        伪随机数        0.5631961
[2024-10-18 15:30:54.159][000000001.938] I/user.crypto        伪随机数        10
[2024-10-18 15:30:54.161][000000001.939] I/user.crypto        伪随机数        13488
[2024-10-18 15:30:54.258][000000002.049] I/user.crypto        真随机数        -1914839329        5
[2024-10-18 15:30:54.269][000000002.050] I/user.crypto        伪随机数        0.7684302
[2024-10-18 15:30:54.272][000000002.051] I/user.crypto        伪随机数        77
[2024-10-18 15:30:54.274][000000002.052] I/user.crypto        伪随机数        30056
[2024-10-18 15:30:54.366][000000002.154] I/user.crypto        真随机数        -974370001        5
[2024-10-18 15:30:54.371][000000002.155] I/user.crypto        伪随机数        0.2707427
[2024-10-18 15:30:54.375][000000002.165] I/user.crypto        伪随机数        11
[2024-10-18 15:30:54.380][000000002.166] I/user.crypto        伪随机数        46138
[2024-10-18 15:30:54.475][000000002.267] I/user.crypto        真随机数        -1427124973        5
[2024-10-18 15:30:54.489][000000002.268] I/user.crypto        伪随机数        0.3834128
[2024-10-18 15:30:54.492][000000002.270] I/user.crypto        伪随机数        88
[2024-10-18 15:30:54.495][000000002.271] I/user.crypto        伪随机数        12880
[2024-10-18 15:30:54.584][000000002.381] I/user.crypto        真随机数        427995234        5
[2024-10-18 15:30:54.596][000000002.382] I/user.crypto        伪随机数        0.3756179
[2024-10-18 15:30:54.601][000000002.383] I/user.crypto        伪随机数        23
[2024-10-18 15:30:54.604][000000002.384] I/user.crypto        伪随机数        20818
[2024-10-18 15:30:54.607][000000002.385] I/user.crypto        ALL Done

七、总结

通过本章内容的学习,你可以学习到有关随机数的函数,例如:crypto.trng(len)、math.random([n [,m]])、math.randomseed(n) 等函数.

八、扩展

8.1 注意事项

需要注意的是,Lua 中的随机数算法可能存在一些问题.例如,math.random(1, 3276700)返回的值最后两位必为 0,这是由于 Lua 本身的随机函数算法决定的.因此,在使用 Lua 生成随机数时,应当注意这些潜在的限制,并尽可能通过设置合适的随机种子来避免生成可预测的随机数序列.

通过以上方法,可以在 Lua 中有效地生成随机数,并确保每次运行程序时都能得到不同的随机数序列,从而满足各种需要随机性的应用场景.

8.2 设置随机数种子

为了确保每次运行程序时都能生成不同的随机数序列,需要使用math.randomseed来设置一个随机种子.通常,使用系统时间os.time()作为种子是一个简单而有效的方法:

math.randomseed(os.time())
然而,如果程序在很短的时间内多次运行,可能会发现生成的随机数序列几乎不变.这是因为os.time()返回的是秒级的时间戳,不够精确.为了解决这个问题,可以将时间戳转换为字符串,然后反转并截取高位数字作为种子:
math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 7)))
这种方法通过提高种子数值的变化量,使得即使在短时间内多次运行程序,也能产生更好的伪随机序列.

给读者的话

本篇文章由公帅开发;

本篇文章描述的内容,如果有错误、细节缺失、细节不清晰或者其他任何问题,总之就是无法解决您遇到的问题;

请登录合宙技术交流论坛,点击文档找错赢奖金-Air780EP-LuatOS-软件指南-基础服务-随机数(random)

用截图标注+文字描述的方式跟帖回复,记录清楚您发现的问题;

我们会迅速核实并且修改文档;

同时也会为您累计找错积分,您还可能赢取月度找错奖金!