浮点比较(1.0 == 1.0)总是错误的

时间:2014-08-05 20:42:15

标签: python python-2.7 kivy

我在Python 2.7.3和Kivy 1.8.0中使用以下函数来淡入Grid小部件:

def __init__(self, **kwargs):
     # ...Init parent class here...
     self.grid.opacity = 0.0
     Clock.schedule_interval(self.show, 1 / 10)

def show(self, value):
    if self.grid.opacity == 1.0:
        return False
    else:
        self.grid.opacity += 0.1

show()无限执行,self.grid.opacity == 1.0总是返回False,因此调度程序永远不会删除该函数。

我想,并且文档说,opacityNumericProperty,默认为1.0,但我正在调用show()之前更改其值。

这是我尝试过的:

if self.grid.opacity == NumericProperty(1.0):

if float(self.grid.opacity) == 1.0:

它不起作用。此外,我确信self.grid.opacity 1.0type()在我进行比较之前检索float

这有效:

if str(self.grid.opacity) == "1.0":

但显然我不喜欢这个解决方案。

有什么想法吗?

5 个答案:

答案 0 :(得分:4)

可能是浮动比较问题。我不知道应用程序,但浮点数永远不会精确,因此测试它们的相等性会导致问题。您可以尝试以下方式:

if abs(float(self.grid.opacity) - 1.0) < .001:
    pass

一个有趣的浮动行为的例子,至少在我的设置上:

>>> .1 + .1 + .1 == .3
False
>>> .1 + .1 == .2
True

答案 1 :(得分:4)

可能不是Python特有的。阅读What Every Programmer Should Know About Floating-Point Arithmetic

0.1不能完全表示为IEEE754双精度浮点数。所以我想浮点(解析自)0.1不完全十分之一)不会转换为字符串“0.1”

答案 2 :(得分:3)

这是你的问题:

>>> q=0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
>>> str(q)
'1.0'
>>> q
0.9999999999999999
>>> q==1
False

底线从不将浮点数与==,期间进行比较。

答案 3 :(得分:2)

正如其他人所说,问题是由于存储浮点数的方式。虽然您可以尝试使用变通方法,但还有更好的方法:Animation

__init__

self.grid.opacity = 0
anim = Animation(opacity=1)
anim.start(self.grid)

答案 4 :(得分:1)

@Basile Starynkevitch回答了为什么会发生这种情况,浮点数的性质在这里起作用。进行这种比较的一般形式是:

abs(numberA - numberB) <= SOMEEPSILON

其中SOMEEPSILON是您认为可接受的保证金。

如果您使用较小的数字并且不担心舍入错误,可以sys.float_info.epsilon

因此,我通过将两者结合起来评论:

abs(self.grid.opacity- 1.0) <= sys.float_info.epsilon

文档中epsilon值的定义是:

difference between 1 and the least value greater than 1 that is representable as a float

这是另一种说法,即1和它之前的数字之间的最小值。

因此,例如,如果python只能表示最多2个小数位的数字,那么epsilon将是1.00和0.99之间的差异(实际上该值远小于此值)