非常简单的问题,但我真的很困惑:P
> for x = 0, 5, 0.2 do
print (x)
end
此循环仅计为4.8 (用0.2再多一步就会得到5,不是吗?)
但是以下for循环计数为5
> for x = 0, 5, 1 do
print (x)
end
有人可以解释或参考手册,这些输出背后的原因。也许我应该将变量定义为float?
答案 0 :(得分:4)
Lua通常用ieee754 binary64格式表示数字("通常"因为表示实际上取决于底层的C实现)。 binary64中的closest number到0.2
为0x3FC999999999999A
,或大约为0.200000000000000011102230246252
。
在进行计算之前,源代码中的0.2
将四舍五入为此数字。
由于0.200000000000000011102230246252
大于2
,因此在最后一步中数字会大于5
,因此循环结束时大约为4.8
。
答案 1 :(得分:3)
for x = 0, 5, 0.2 do print (x) end
此数字for
循环会将步骤0.2
添加到初始值0
,执行处理(print(x)
),直到值为<=5
。问题是,对于浮点数,0.2
无法精确表示,因此有一点点四舍五入。所以当你认为它应该总和为5
时,它可能会更大一些。
对于不是很大的整数,它可以用双精度浮点数精确表示,所以没问题。
对于你学习Lua的第一天,一点小贴士:
double
。 *见下文 *
:这不再是真的。 Lua 5.3为数字引入了一个新的整数子类型。见Changes in the Language
答案 2 :(得分:1)
像往常一样,当使用任何语言的浮点数/双打时,你会发现一些奇怪的事情,搜索浮点数/双打如何以特定语言存储。
已经回答here
正如 @jbr 已经注意到的那样,0.2存储为0.2000000000000000111022302462515654042363166809082031250000000000
,当for循环运行时,它会检查该值是否小于或等于5,并且因为它们的总和双精度大于5,它不会将其解释为此循环的成员并立即退出。
答案 3 :(得分:1)
你在这里遇到的是许多人在Lua中感到困惑的事情。在Lua中,所有数字都是双精度数,这意味着并非所有数字都有精确的表示,0.2
就是其中一个数字:
> print(string.format("%1.64f",math.abs(0.2)))
0.2000000000000000111022302462515654042363166809082031250000000000
所以你得到的是一个累积的错误。
如果您尝试0.25
:
> print(string.format("%1.64f",math.abs(0.25)))
0.2500000000000000000000000000000000000000000000000000000000000000
所以
for x = 0, 5, 0.25 do
print(x)
end
按预期工作,有关详细信息,请参阅Lua fails to evaluate math.abs(29.7 - 30) <= 0.3