跳转至

随机数(random)

作者:沈园园 | 最后修改:2026-08-19

一、random 概述

随机数是专门的随机试验的结果。

在统计学的不同技术中需要使用随机数,比如在从统计总体中抽取有代表性的样本的时候,或者在将实验动物分配到不同的试验组的过程中,或者在进行蒙特卡罗模拟法计算的时候等等。

产生随机数有多种不同的方法,这些方法被称为随机数生成器。随机数最重要的特性是它在产生时后面的那个数与前面的那个数毫无关系。

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

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

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

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

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

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

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

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

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

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

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

二、演示功能概述

本篇文章通过 Air724UG 的核心板烧录底层固件和修改 LuatOS 示例代码,来演示有关随机数的各种 API 的功能。

本 demo 演示的核心功能为:

  1. 使用 crypto.trng(len) 生成真随机数;

  2. 使用 math.random([n [,m]]) 生成伪随机数;

  3. 使用 math.randomseed(n) 设置随机数种子。

三、准备硬件环境

1、Air724UG核心板一块

Air724UG核心板

2、TYPE-C USB数据线一根

3、Air724UG核心板和数据线的硬件接线方式为

  • Air724UG核心板通过TYPE-C USB口连接TYPE-C USB 数据线,数据线的另外一端连接电脑的USB口;

  • Air724UG核心板通过TYPE-C USB口供电;

Air724UG 核心板购买链接:合宙官方淘宝店铺

四、准备软件环境

4.1 软件环境

在开始实践本示例之前,先筹备一下软件环境:

1、烧录工具:Luatools 下载调试工具

2、本demo开发测试时使用的固件为Air724 LuatOS固件,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;

3、脚本文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air724/demo/random

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

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

4.2 API 介绍

crypto库:https://docs.openluat.com/osapi/core/crypto/

math库(Lua标准库):math.randommath.randomseed 是 Lua 标准库自带函数,无需额外引入,直接使用即可。

五、程序结构

random/
│── main.lua
│── random_app.lua
│── readme.md

5.1 文件说明

  1. main.lua:主程序入口文件,负责定义项目名和版本号、加载业务模块,最后调用 sys.run() 启动 LuatOS 运行框架。

  2. random_app.lua:随机数应用功能模块,演示真随机数、伪随机数的生成方法和随机数种子的设置方法。

  3. readme.md:使用说明文档。

六、代码详解

6.1 main.lua

主程序文件 main.lua 是整个项目的入口点。它负责定义 PROJECT 和 VERSION 变量、打印项目信息、加载业务模块,最后调用 sys.run() 启动 LuatOS 运行框架。

--[[
@module  main
@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
@version 1.0
@date    2026.08.19
@author  沈园园
@usage
本demo演示的核心功能为:
随机数的生成与使用(真随机数 crypto.trng、伪随机数 math.random、随机数种子 math.randomseed)
更多说明参考本目录下的readme.md文件
]]

PROJECT = "random_demo"
VERSION = "001.999.000"

-- 在日志中打印项目名和项目版本号
log.info("main", PROJECT, VERSION)

-- 加载 random_app 主应用功能模块
require "random_app"

-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!

6.2 random_app.lua

随机数应用功能模块,核心业务逻辑为:设置随机数种子后,循环输出真随机数和伪随机数。

6.2.1 随机数测试

-- 随机数任务主函数
local function random_task_func()
    sys.wait(1000)      -- 等待系统稳定,1000ms

    -- 随机数测试:设置随机数种子后,循环输出真随机数和伪随机数
    log.info("random_app", "===== [1/1] 随机数测试 =====")
    math.randomseed(os.time())  -- 使用系统时间设置随机数种子
    for i = 1, 10 do
        sys.wait(100)   -- 每次输出间隔,100ms
        log.info("crypto", "真随机数", string.unpack("I", crypto.trng(4)))  -- 生成4字节真随机数并解包为整数
        log.info("crypto", "伪随机数", math.random())       -- 无参调用,输出[0,1)之间的浮点数,不推荐
        log.info("crypto", "伪随机数", math.random(100))    -- 一个参数n,输出1-100之间的随机整数
        log.info("crypto", "伪随机数", math.random(1, 65525))  -- 两个参数n,m,输出1-65525之间的随机整数,不推荐
    end
    log.info("crypto", "ALL Done")

    log.info("random_app", "===== [演示完毕] =====")
end

-- 创建一个task,并且运行task的主函数random_task_func
sys.taskInit(random_task_func)

七、运行结果展示

出现类似于下面的日志,就表示运行成功:

[2026-08-19 10:15:32.156][000000000.246] I/user.main        random_demo        001.999.000
[2026-08-19 10:15:33.248][000000001.276] I/user.random_app        ===== [1/1] 随机数测试 =====
[2026-08-19 10:15:33.358][000000001.386] I/user.crypto        真随机数        -2126957010        5
[2026-08-19 10:15:33.369][000000001.388] I/user.crypto        伪随机数        0.4636298
[2026-08-19 10:15:33.373][000000001.389] I/user.crypto        伪随机数        50
[2026-08-19 10:15:33.375][000000001.390] I/user.crypto        伪随机数        46998
[2026-08-19 10:15:34.358][000000001.486] I/user.crypto        真随机数        -309051301        5
[2026-08-19 10:15:34.369][000000001.488] I/user.crypto        伪随机数        0.6394390
[2026-08-19 10:15:34.373][000000001.489] I/user.crypto        伪随机数        10
[2026-08-19 10:15:34.375][000000001.490] I/user.crypto        伪随机数        38883
[2026-08-19 10:15:35.358][000000001.586] I/user.crypto        真随机数        -1863938574        5
[2026-08-19 10:15:35.369][000000001.588] I/user.crypto        伪随机数        0.9536643
[2026-08-19 10:15:35.373][000000001.589] I/user.crypto        伪随机数        25
[2026-08-19 10:15:35.375][000000001.590] I/user.crypto        伪随机数        16512
...
[2026-08-19 10:15:42.107][000000002.385] I/user.crypto        ALL Done
[2026-08-19 10:15:42.108][000000002.386] I/user.random_app        ===== [演示完毕] =====

日志中的真随机数和伪随机数每次运行都会不同,这是随机数的正常特性;其中真随机数后面的数字 5 是 string.unpack 函数返回的下一个读取位置,无需关注。

八、总结

通过本文学习,你可以学习到随机数的相关知识,以及 crypto.trng(len)math.random([n [,m]])math.randomseed(n) 等函数的使用方法,为后续学习更加复杂的业务逻辑打下基础。

搜索