lua – 奇怪的循环问题

我不确定这是不是一个bug,所以我想也许你们大家可能想看一看.

问题出在这个代码上:

for i=0,1,.05 do
    print(i)
end

输出应该是:

0
.05
.1
--snip--
.95
1

相反,输出是:

0
.05
.1
--snip--
.95

while循环也发生了同样的问题:

w = 0
while w <= 1 do
    print(w)
    w = w + .05
end
--output:
0
.05
.1
--snip--
.95

w的值为1,可以在循环后通过print语句验证.

我已尽可能验证任何小于或等于0.05的步骤都会产生此错误.任何高于.05的步骤应该没问题.我确认1/19(0.052631579)确实打印了1.(显然,像19.9或10.5这样的小数分母不会产生[0,1]包含的输出.)是否有可能这不是语言的错误?解释器和常规Lua文件都会产生此错误.

这是一个四舍五入的问题.问题是0.05表示为浮点二进制数,并且它没有二进制的精确表示.在基数2(二进制)中,它是一个重复的十进制数,类似于数字,如基数为10的数字.当重复添加时,舍入产生的数字略大于1.它只是非常非常略大于1 ,所以如果你打印出来,它会显示1作为输出,但它不是1.

> x=0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05
> print(x)
1
> print(1==x)
false
> print(x-1)
2.2204460492503e-16

所以,正如你所看到的,虽然真的接近1,但它实际上略微更多.

当我们有重复分数时,类似的情况可以以十进制形式出现.如果我们将1/3 1/3 1/3加在一起,但我们必须舍入到六位数才能使用,我们将添加0.333333 0.333333 0.333333并得到0.999999,这实际上不是1.这是二进制的类似情况数学. 1/20不能用二进制精确表示.

注意,对于乘法,舍入略有不同

> print(0.05*20-1)
0
> print(0.05*20==1)
true

因此,您可以重写代码来说明

for i=0,20,1 do
    print(i*0.05)
end

它会正常工作.一般情况下,建议不要使用浮点数(即带小数点的数字)来控制循环,这样可以避免.

相关文章
相关标签/搜索