Lua数字比较返回错误结果:Hammerspoon定时器逻辑异常
浮点数精度问题导致Hammerspoon定时器无法正确停止
你遇到的问题核心是浮点数精度误差:Lua使用双精度浮点数存储数值,而0.1这类十进制小数无法被二进制浮点数精确表示。每次执行i = i + .1时,都会积累微小的误差,最终i的实际值会是类似4.999999999999999或5.000000000000001的数值,和整数5直接用==比较自然会返回false——哪怕5 == 5.0本身是成立的。
修复方案1:用整数计数彻底规避浮点数问题
既然定时器每次触发间隔是0.1秒,总时长5秒,那总触发次数就是50次,用整数计数可以完全避免精度问题:
local function startTimer() local totalTicks = 50 -- 5秒 ÷ 0.1秒/次 = 50次 local i = 0 local function onTimeout() i = i + 1 local stopTimer = i == totalTicks print('stopTimer:', stopTimer) print(i, totalTicks, type(i), type(totalTicks)) if stopTimer then timer:stop() end end local timer = hs.timer.new(.1, onTimeout) timer:start() end
修复方案2:用近似相等判断
如果必须保留秒数累加的逻辑,可以通过判断两个数值的差值绝对值是否小于一个极小值(比如1e-9)来近似判断相等:
local function startTimer() local totalSeconds = 5 local i = 0 local function onTimeout() i = i + .1 -- 当差值小于1e-9时,认为两个数值相等 local stopTimer = math.abs(i - totalSeconds) < 1e-9 print('stopTimer:', stopTimer) print(i, totalSeconds, type(i), type(totalSeconds), 5 == 5.0) if stopTimer then timer:stop() end end local timer = hs.timer.new(.1, onTimeout) timer:start() end
两种方案里,方案1的可靠性更高,完全规避了浮点数带来的精度风险;方案2适合需要直接处理秒数的场景。
内容的提问来源于stack exchange,提问作者nik
相关产品推荐
相关产品推荐

