如何可靠地从任意数字中保留指定小数位数(Lua)
Lua 保留指定位小数函数的优化方案
我编写了Lua函数remove_decimal,期望通过参数dec指定保留的小数位数,但当前实现存在问题,比如处理多整数位数字时会异常。虽修改后能运行,但想寻求更优方案。
当前函数代码
local function remove_decimal(t, dec) if type(dec) == "number" then for key, num in pairs(type(t) == "table" and t or {}) do if type(num) == "number" then local num_to_string = tostring(num) local mod, d = math.modf(num) -- 提取小数部分 local num_dec = num_to_string:sub(#tostring(mod) + (mod == 0 and num < 0 and 3 or 2)) if dec <= #num_dec then -- 拼接指定长度的小数部分 local r = d < 0 and "-0." or "0." local r2 = r .. num_dec:sub(1, dec) t[key] = mod + tonumber(r2) end end end end return t end
期望调用结果
调用函数后需得到以下输出:
-- 预期输出: -- 0.12 -- -0.12 -- 123.45 -- -1.23 local result = remove_decimal({0.123, -0.123, 123.456, -1.234}, 2) print(result[1]) print(result[2]) print(result[3]) print(result[4])
此前尝试的代码
曾试过以下实现,但仅适用于单整数位数字,比如处理12.34时会错误地变成12.3:
local d = dec + (num < 0 and 2 or 1) local r = tonumber(num_to_string:sub(1, -#num_to_string - d)) or 0
优化方案
推荐用数学运算替代字符串处理,避免字符串操作中对整数位、正负号的复杂判断,兼容性更强:
local function remove_decimal(t, dec) -- 校验参数合法性:dec必须是非负整数 if type(dec) ~= "number" or dec < 0 or math.floor(dec) ~= dec then return t end local scale = 10 ^ dec for key, num in pairs(type(t) == "table" and t or {}) do if type(num) == "number" then -- 缩放数值后截断小数部分,再还原回原量级 local scaled = num * scale local truncated = math.modf(scaled) t[key] = truncated / scale end end return t end
方案优势
- 逻辑简洁:通过数学缩放+截断的方式,无需处理字符串拆分、正负号特殊判断等复杂逻辑
- 兼容性强:完美支持多整数位数字、负数、零等各种数值场景
- 性能更优:数学运算比字符串操作的执行效率更高
测试上述优化后的函数,运行示例代码可得到完全符合预期的输出。
内容的提问来源于stack exchange,提问作者Playhouse
相关产品推荐
相关产品推荐

