1. Lua浮点型精度问题初探
最近在游戏开发中遇到一个有趣的案例:策划要求比分显示必须精确到小数点后两位,但不能进行四舍五入。比如1.9999必须显示为1.99,而不是2.00。这个看似简单的需求,却让我掉进了Lua浮点型运算的精度陷阱。
Lua的number类型底层其实是双精度浮点数(double),采用IEEE 754标准。这意味着它能表示大约16-17位有效数字。但浮点数的二进制特性导致它在处理十进制小数时,经常会出现精度丢失的问题。比如在Lua中直接打印0.1 + 0.2,你会得到0.30000000000000004而不是预期的0.3。
在游戏开发中,比分计算经常涉及浮点运算。比如玩家得分可能是击杀数乘以系数(如1.75),这时如果简单使用string.format("%.2f", score),就会遇到四舍六入的问题。我最初尝试的代码是这样的:
function FormatScore(val)
local temp = tonumber(val) * 100
return tonumber(string.format("%.2f", temp / 100))
end
看起来逻辑很清晰:先把数值放大100倍,取两位小数后再缩小。但实测发现这个方案根本达不到"截断"效果,因为它底层调用的string.format采用的是银行家舍入法(四舍六入五成双),而不是简单的截取。
2. 四舍六入的真相
2.1 银行家舍入法解析
大多数开发者以为string.format做的是四舍五入,其实这是个常见误解。Lua(以及C语言)实际采用的是IEEE标准推荐的银行家舍入法(Banker's Rounding),规则如下:
- 小于5舍去:1.54 → 1.5
- 大于5进位:1.56 → 1.6
- 等于5看奇偶

734

被折叠的 条评论
为什么被折叠?



