一、概述
本文档基于 LuatOS 在 Air780EPM 设备上的测试结果,详细分析 32 位和 64 位固件在整数处理、浮点数精度和性能方面的差异。
二、核心差异总结
2.1 整数处理能力
整数范围
溢出行为
- 32 位固件:整数溢出时发生环绕(wrap-around)
lua
2147483647 + 1 = -2147483648
- 64 位固件:同样存在环绕行为,但范围更大
lua
9223372036854775807 + 1 = -9223372036854775808
2.2 浮点数精度表现
基础精度测试
误差累积测试(连续除法)
关键发现:
- 32 位固件:在 10^40 次方后精度显著下降
lua
除以10^40后: 3.099994502e-40 -- 误差开始明显
除以10^45后: 2.802596912e-45 -- 严重失真
- 64 位固件:在整个测试范围内保持较好精度
lua
除以10^45后: 3.099999982e-45 -- 仍保持较高精度
经典一致性测试
-
32 位固件:
0.1 + 0.2 == 0.3返回true -
实际存储值相同:0.30000001200000000000
-
因精度限制,误差被掩盖
-
64 位固件:
0.1 + 0.2 == 0.3返回false -
显示值相同但实际存储存在微小差异
-
更高精度暴露了浮点运算的本质问题
三、 性能对比
3.1 运算速度
Flash/内存占用差异
编译时 Flash
64 位固件会比 32 位固件多使用 10KB 的 Flash 代码空间
运行时内存
3.2 功耗对比测试
分别连续做 10 秒钟整数运算、小数运算、位运算
32 位固件

64 位固件

四、实际应用影响
适合 32 位固件的场景
- 内存敏感型应用:内存占用略低
- 整数范围需求小:处理数值在 ±21 亿以内
- 精度要求不高:对浮点数精度要求较低的场合
适合 64 位固件的场景
- 大数据处理:需要处理超大整数
- 高精度计算:科学计算、财务应用等
- 长期运行系统:更好的数值稳定性
五、技术建议
5.1 开发注意事项
- 整数溢出处理:两种架构都需要注意整数溢出问题
- 浮点数比较:避免直接比较浮点数相等,应使用误差范围
5.2 迁移建议
从 32 位迁移到 64 位时:
- 检查所有整数运算的边界条件
- 验证浮点数精度是否满足要求
- 测试性能提升效果
测试代码:
lua
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)