【问题标题】:Float comparison (1.0 == 1.0) always false浮点比较 (1.0 == 1.0) 始终为假
【发布时间】:2014-08-05 20:42:15
【问题描述】:

我在 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.opacity1.0 并且type() 在我进行比较之前检索float

这行得通:

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

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

有什么想法吗?

【问题讨论】:

  • 有很多资源可以解释浮点数及其不精确性。您是否搜索过 SO(甚至使用谷歌)?
  • 这并不意味着0.1 + 0.1 + 0.1 ... == 1.0
  • 我认为这被标记为错误的副本。 stackoverflow.com/questions/5595425/… 在这里更相关。对于这两个问题,也没有人在 Python 中提到 epsilon。
  • @cdonts:您可能会感到困惑,因为您查看的是str(somenumber) 而不是repr(somenumber)。尝试print(repr(self.grid.opacity), self.grid.opacity-1) 说服自己您正在查看 0.9999999999999999。

标签: python python-2.7 kivy


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案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
      

      底线永远不要将浮点数与 ==、句号进行比较。

      【讨论】:

      • 那么替代解决方案是什么?
      【解决方案4】:

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

      __init__:

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

      【讨论】:

        【解决方案5】:

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

        abs(numberA - numberB) &lt;= SOMEEPSILON

        其中SOMEEPSILON 是您认为可接受的边距的数字。

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

        正如我评论的那样,将两者结合起来:

        abs(self.grid.opacity- 1.0) &lt;= 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 之间的差值(实际上这个值要小得多)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-16
          • 1970-01-01
          • 2016-07-03
          • 1970-01-01
          • 2017-01-07
          • 2016-02-22
          • 2016-01-19
          • 2020-03-15
          相关资源
          最近更新 更多