代码之家  ›  专栏  ›  技术社区  ›  max

python中的近似比较

  •  3
  • max  · 技术社区  · 14 年前

    我想让“==”运算符在我的程序中使用近似比较:如果

    abs(x-y)/(0.5(x+y)) < 0.001
    

    有什么好办法?既然float是一个内置类型,我想我不能重新定义==操作符,可以吗?

    注意,我想使用float的其他特性,我唯一想更改的是equality操作符。

    编辑:

    谢谢你的回答,我理解你关于可读性和其他问题的论点。

    也就是说,如果可能的话,我真的更愿意继续使用常规的float类型,而不是使用一个新的类或一个新的比较函数。是否甚至可以为常规浮点重新定义==运算符?

    我的理由是:

    (a)每个使用我正在编写的程序的人都希望用这种方式比较浮动

    (B)在这个世界上,没有任何人会愿意使用默认值==来表示浮动。为什么用这种语言????

    (c)我不喜欢代码中有多余的单词;显然,使用现有的float不会导致代码发生任何变化。

    编辑2。

    既然我知道我不能重载float的==操作符,我必须改变我的问题。它将变得如此不同,我将在 custom comparison for built-in containers

    3 回复  |  直到 12 年前
        1
  •  7
  •   John Machin Santi    13 年前

    您的定义有两个问题:

    1. 缺少一个 *

    2. 如果 x + y == 0.0 (包括可能经常发生的案件) x == y == 0.0 )

    试试这个:

    define approx_Equal(x, y, tolerance=0.001):
        return abs(x-y) <= 0.5 * tolerance * (x + y)
    

    编辑:注意使用 <= 而不是 < …需要使 x==y=0 箱子工作正常。

    我不会试图超越 ==

    编辑2:你写了:

    世界上没有任何人愿意使用默认值 =对于浮点数..为什么用这种语言????

    没办法?假设您有一个返回浮点值的函数,并且您有一个关于一个算法的脑波,该算法可以更快、更优雅地生成相同的答案;您如何测试它?

        2
  •  18
  •   AndiDog    12 年前

    您可以创建一个从内置浮点类型派生的新类,然后覆盖必要的运算符:

    class InexactFloat(float):
        def __eq__(self, other):
            try:
                return abs(self.real - other) / (0.5 * (abs(self.real) + abs(other))) < 0.001
            except ZeroDivisionError:
                # Could do another inexact comparison here, this is just an example:
                return self.real == other
    
        def __ne__(self, other):
            return not self.__eq__(other)
    
    print 5.2 == 5.20000000000001 # False
    print 5.2 != 5.20000000000001 # True
    print InexactFloat(5.2) == InexactFloat(5.20000000000001) # True
    print InexactFloat(5.2) != InexactFloat(5.20000000000001) # False
    print InexactFloat(-5) == -5 # True
    
    # Works for InexactFloat <-> float comparison
    print 5.0 == InexactFloat(5.0) # True
    print InexactFloat(5.0) == 5.0 # True
    
    # Zero division case (note how I implemented it above!)
    print InexactFloat(-0.00001) == InexactFloat(0.00001) # False
    print InexactFloat(-0.000000001) == InexactFloat(0.000000001) # False
    print InexactFloat(-5) == InexactFloat(5) # False
    
    # Unit test for fixed negative numbers problem
    print InexactFloat(-5) == InexactFloat(-10) # False
    

    您可能还需要覆盖<=等运算符。

        3
  •  3
  •   MdaG    14 年前

    如果将数字包装在类中,则可以使用以下方法重载“==”:

    def __eq__(self, x):
       return abs(x - self.x) / (0.5 * (x + self.x)) < 0.001
    

    但是,您应该将表达式重写为

    abs(x - self.x) < 0.0005 * (x + self.x)

    以避免零除。