奇怪的python while循环行为与<对照

时间:2012-01-18 17:37:23

标签: python while-loop

我对这段代码感到困惑:

t=0
while  t<5:  #currently loop runs for 10 seconds
    print "in loop",t
    if (t<5):
        print "true"
    t=t+0.01

在循环的最后一次运行中打印:

in loop 5.0 
true

现在,如果在最后一次通过循环时t = 5.0,那么t&lt; 5中的if语句不符合?而且,它不应该甚至没有在t = 5的循环中运行,因为它也应该在while条件下失败了吗?

6 个答案:

答案 0 :(得分:3)

5不一定是5:

t=0
while  t<5:  #currently loop runs for 10 seconds
    print "in loop",t, repr(t)
    if (t<5):
        print "true"
    t=t+0.1

产生

in loop 0 0
true
in loop 0.1 0.1
true
in loop 0.2 0.2
true
in loop 0.3 0.30000000000000004

[...]

in loop 4.8 4.799999999999999
true
in loop 4.9 4.899999999999999
true
in loop 5.0 4.999999999999998
true

0.1无法用二进制表示。

[啊,我只是注意到我使用了0.1而不是0.01,就像你做的那样。嗯,这是同样的问题。]

两个“浮点如何工作”引用:classicalgentler

答案 1 :(得分:1)

这是因为打印时值已四舍五入。这绝对是人们所期望的。

如果您需要避免此行为,请以不同方式格式化输出,或使用适当的增量进行测试,例如: 5.0 - t < delta

delta是您喜欢的任何数值 - 它定义了为了您的目的接近5等于5的情况,因为通常使用纯二进制表示法无法精确表示十进制值。

如果在您的应用程序中这是不可接受的,则替代方法是使用在内部使用十进制表示的十进制类。

答案 2 :(得分:1)

最后一次循环迭代中t的值接近但不到5.0。不可能精确地以二进制形式表示0.01,因此每次将{0.01}添加到t时会出现小错误。 Python认为结果足够接近5.0以打印“5.0”,但它实际上并不是5.0。

要使其按预期工作,请使用Decimal,这不会受到这些舍入错误的影响。

from decimal import Decimal
t=Decimal("0")
while  t<5:
    print "in loop",t
    if (t<5):
        print "true"
    t=t+Decimal("0.01")

答案 3 :(得分:0)

问题是精度错误。如果您将其更改为:

t=0
while  t<5:  #currently loop runs for 10 seconds
    print "in loop",repr(t)
    if (t<5):
        print "true"
    t=t+0.01

你会看到通过循环t的最后一次实际上是4.999999999999938。

Python(以及大多数其他编程语言)无法准确表示所有实数,因此您最终会遇到令人惊讶的行为。

答案 4 :(得分:0)

基于使用delta的Marcin's recommendation,这是一个可行的解决方案:

>>> step = 0.01
>>> t = 4.9
>>> while 5.0 - t > step:
        print 'in loop', t
        t += step


in loop 4.9
in loop 4.91
in loop 4.92
in loop 4.93
in loop 4.94
in loop 4.95
in loop 4.96
in loop 4.97
in loop 4.98
in loop 4.99

答案 5 :(得分:0)

另一种看待它的方式是二进制中的0.1类似于基数10中的1/3(即0.333333)。它不能用有限数字表示。当您键入0.1时,Python会将其转换为二进制,但(显然)使用有限数量的位进行转换,因此它不是 0.1。所以基本上这里发生的是一个假设的计算机,它在10号基础上工作:

count = 0
while count != 1:
    count += 0.33333333333

当然,计数永远不会是1,while循环将继续运行。