Lua中如何在不改变整数值的前提下去除小数尾缀.0
问题根因
Lua 中数值运算默认会将整数运算结果转为浮点数类型,直接调用tostring()处理浮点数类型的整数值时,就会自动追加.0后缀。你使用math.floor/math.ceil会修改原值的本质原因是运算过程中可能出现的浮点数精度误差:比如理论上应该得到114的运算,实际运行时可能得到113.9999999999999或者114.0000000000001,直接取整就会出现偏差。
解决方案
你可以先对运算后的值做整数判定,再选择对应的转字符串方式,这里提供两个可行方案:
方案1:精度修正后判定转整数(推荐)
先给运算结果加一个极小的容错偏移量(比如1e-6)抵消浮点数精度误差,再判断是否为整数,是就转整数类型再转字符串,否则保留原有小数:
-- 新增通用的数值转字符串工具函数 local function num2str(num) -- 极小偏移量修正浮点数精度误差 local epsilon = 1e-6 local rounded = math.floor(num + epsilon) if math.abs(num - rounded) < epsilon then -- 确认是整数,转整数后再转字符串 return tostring(math.tointeger(rounded)) end -- 非整数保留原有格式 return tostring(num) end
如果使用低于5.3的Lua版本,把math.tointeger(rounded)替换为string.format("%d", rounded)即可。
之后把你customEnc、customDec两个函数里所有tostring(newVar)的调用,全部替换成num2str(newVar)即可。
方案2:字符串替换处理(快速兼容)
如果你的业务场景不会出现非整数的运算结果,也可以在转字符串后直接替换掉结尾的.0后缀,无需修改逻辑:
-- 直接替换原有tostring(newVar)即可 tostring(newVar):gsub("%.0$", "")
修正后的代码示例
local OVal = math.random(1, 999) local SVal = math.random(1, 999) local TVal = math.random(1, 999) local function num2str(num) local epsilon = 1e-6 local rounded = math.floor(num + epsilon) if math.abs(num - rounded) < epsilon then return tostring(math.tointeger(rounded)) end return tostring(num) end local function customEnc(STR) local currentVar = "" local strings = {} STR:gsub(".", function(c) if c == [[\]] then local newVar = tonumber(currentVar) if newVar ~= nil then newVar = newVar * OVal / SVal table.insert(strings, num2str(newVar)) end currentVar = "" else currentVar = currentVar .. c end end) local newString = "" for i,v in pairs(strings) do newString = newString .. [[\]] .. v end newString = newString .. [[\]] return newString end local function customDec(STR) local currentVar = "" local strings = {} STR:gsub(".", function(c) if c == [[\]] then local newVar = tonumber(currentVar) if newVar ~= nil then newVar = newVar / OVal * SVal table.insert(strings, num2str(newVar)) end currentVar = "" else currentVar = currentVar .. c end end) local newString = "" for i,v in pairs(strings) do newString = newString .. [[\]] .. v end newString = newString .. [[\]] return newString end
内容的提问来源于stack exchange,提问作者Joakim Hjalmarsson
相关产品推荐
相关产品推荐

