32 位与 64 位固件使用场景
作者:魏健强 | 最后修改:2026-03-09
概述
本文档基于 LuatOS 在 Air780EPM 设备上的测试结果,详细分析 32 位和 64 位固件在整数处理、浮点数精度和性能方面的差异。
核心差异总结
整数处理能力
整数范围
| 特性 | 32位固件 | 64位固件 |
|---|---|---|
| 整数位宽 | 32位 | 64位 |
| 最大整数 | 2,147,483,647 | 9,223,372,036,854,775,807 |
| 最小整数 | -2,147,483,648 | -9,223,372,036,854,775,808 |
| 十六进制表示 | 0x7FFFFFFF / 0x80000000 | 0x7FFFFFFFFFFFFFFF / 0x8000000000000000 |
溢出行为
- 32 位固件:整数溢出时发生环绕(wrap-around)
2147483647 + 1 = -2147483648
- 64 位固件:同样存在环绕行为,但范围更大
9223372036854775807 + 1 = -9223372036854775808
浮点数精度表现
基础精度测试
| 测试项 | 32位固件 | 64位固件 |
|---|---|---|
| 圆周率显示 | 3.141593 | 3.1415926540000 |
| 圆周率显示 | 约7位有效数字 | 约15位有效数字 |
误差累积测试(连续除法)
关键发现:
- 32 位固件:在 10^40 次方后精度显著下降
除以10^40后: 3.099994502e-40 -- 误差开始明显
除以10^45后: 2.802596912e-45 -- 严重失真
- 64 位固件:在整个测试范围内保持较好精度
除以10^45后: 3.099999982e-45 -- 仍保持较高精度
经典一致性测试
-
32 位固件:
0.1 + 0.2 == 0.3返回true -
实际存储值相同:0.30000001200000000000
- 因精度限制,误差被掩盖
-
64 位固件:
0.1 + 0.2 == 0.3返回false -
显示值相同但实际存储存在微小差异
- 更高精度暴露了浮点运算的本质问题
性能对比
运算速度
| 测试项 时间单位毫秒 | 32位固件 | 64位固件 |
|---|---|---|
| for循环1000000次整数运算耗时 | 1969 | 2057 |
| for循环5000000次整数运算耗时 | 9747 | 10188 |
Flash/内存占用差异
编译时 Flash
64 位固件会比 32 位固件多使用 10KB 的 Flash 代码空间
运行时内存
| 组件 | 32位固件 | 64位固件 | 差异 |
|---|---|---|---|
| Lua虚拟机 | 1,048,568字节 | 1,048,568字节 | 相同 |
| 系统库 | 2,374,608字节 | 2,392,520字节 | 0.0075 |
| PSRAM使用 | 59,388字节 | 59,388字节 | 相同 |
功耗对比测试
分别连续做 10 秒钟整数运算、小数运算、位运算
32 位固件

64 位固件

实际应用影响
适合 32 位固件的场景
- 内存敏感型应用:内存占用略低
- 整数范围需求小:处理数值在 ±21 亿以内
- 精度要求不高:对浮点数精度要求较低的场合
适合 64 位固件的场景
- 大数据处理:需要处理超大整数
- 高精度计算:科学计算、财务应用等
- 长期运行系统:更好的数值稳定性
技术建议
开发注意事项
- 整数溢出处理:两种架构都需要注意整数溢出问题
- 浮点数比较:避免直接比较浮点数相等,应使用误差范围
迁移建议
从 32 位迁移到 64 位时:
- 检查所有整数运算的边界条件
- 验证浮点数精度是否满足要求
- 测试性能提升效果
测试代码:
function test()
log.info("sys", "Lua整数处理能力对比测试开始")
-- log.info("sys", "运行环境: " .. (string.packsize("T") == 8 and "64位" or "32位") .. " Lua 5.3")
-- 获取环境信息
log.info("\n===== 测试1: 环境信息与整数范围 =====")
log.info("整数类型:", math.type(42))
log.info("整数默认大小:", string.packsize("j")) -- Lua 5.3 中 'j' 表示 Lua_Integer
log.info("Lua整数位宽:", string.packsize("j") * 8, "位")
-- 测试整数范围
log.info("\nLua整数范围测试:")
if math.maxinteger then
log.info("math.maxinteger =", math.maxinteger)
log.info("math.mininteger =", math.mininteger)
log.info("十六进制表示:")
log.info(" maxinteger (十六进制):", string.format("0x%X", math.maxinteger))
log.info(" mininteger (十六进制):", string.format("0x%X", math.mininteger))
else
log.info("注意: 您的Lua版本不支持 math.maxinteger/mininteger")
-- 手动测试整数范围
local max_int = 2^31 - 1 -- 假设32位
local min_int = -2^31
log.info("假设整数范围: ", min_int, "到", max_int)
end
-- 测试2: 整数溢出行为
log.info("\n===== 测试2: 整数溢出行为测试 =====")
log.info("--- 32位边界测试 ---")
local int32_max = math.maxinteger
local int32_min = math.mininteger
log.info("int32_max =", int32_max)
log.info("int32_max + 1 =", int32_max + 1)
log.info("int32_max + 2 =", int32_max + 2)
log.info("int32_min =", int32_min)
log.info("int32_min - 1 =", int32_min - 1)
log.info("int32_min - 2 =", int32_min - 2)
log.info("sys", "Lua浮点数精度对比测试开始")
-- log.info("sys", "预计运行环境: " .. (string.packsize("T") == 8 and "64位" or "32位"))
-- 测试1: 基础精度与有效数字测试
-- 目的:直接展示两种精度能保留多少位有效数字
log.info("\n===== 测试1: 基础精度 (有效数字位数) =====")
local pi_high_precision = 3.14159265358979323846 -- 多位圆周率
log.info("高精度圆周率值: ", pi_high_precision)
log.info("默认输出: ", ("%.15f"):format(pi_high_precision))
log.info("科学计数法: ", ("%.15e"):format(pi_high_precision))
-- 测试2: 经典浮点误差放大测试 (基于您的原始代码优化)
-- 目的:展示连续运算下的误差累积与放大过程
log.info("\n===== 测试2: 误差累积测试 (连续除法) =====")
local num = 3.1
log.info("初始值: ", num, " (注意:3.1无法用二进制精确表示)")
for i = 1, 45 do
num = num / 10
log.info(("除以10^%2d 后: %-25s (十六进制: %s)"):format(
i,
("%.20e"):format(num), -- 显示20位科学计数,看清细节
("%a"):format(num) -- %a格式:以十六进制显示浮点数的精确位表示
))
end
-- 测试4: 一致性测试 (经典问题)
-- 目的:展示因精度限制导致的违反直觉的结果
log.info("\n===== 测试4: 经典一致性测试 =====")
log.info("0.1 + 0.2 == 0.3 ?", 0.1 + 0.2 == 0.3)
log.info("0.1 + 0.2 的实际值: ", ("%.20f"):format(0.1 + 0.2))
log.info("0.3 的实际存储值: ", ("%.20f"):format(0.3))
log.info("sys", "浮点数精度测试结束")
end
sys.taskInit(test)
function sum_time_test()
local tick1 = mcu.ticks()
local num = 0
for i = 1, 5000000 do
num = num + 111
end
local tick2 = mcu.ticks()
local diff_ticks = tick2 - tick1
log.info("sys", "5000000次整数运算耗时:", diff_ticks .. "毫秒")
end
sys.taskInit(sum_time_test)