number comparison problem

Jeff Epler jepler at unpythonic.net
Wed Oct 16 09:53:36 EDT 2002


On Tue, Oct 15, 2002 at 08:10:09PM -0700, Chris Fonnesbeck wrote:
> These numbers look the same to me; what do I have to do to be able to
> test numbers accurately in python?

The number has been tested accurately.  Consider the following example:
>>> x = .5
>>> y = x + .5 ** 53  # The smallest IEEE double greater than x
>>> print x, y  # prints with low precision
0.5 0.5
>>> x == y
False
>>> cmp(x, y)
-1
>>> print repr(x), repr(y)  # prints with full precision
0.5 0.50000000000000011
>>> y-x # also prints full precision
1.1102230246251565e-16

You could use something like the following to compare floats:
    def fcmp(a, b):
        # Let eps be relative to the larger value
        #eps = max(abs(a), abs(b)) / 1e5
        # Or let it be an absolute value
        eps = 1e-5
        if abs(b-a) < eps:
            return 0
        return cmp(a, b)
In newer versions you could even derive your own class from float and
replace __cmp__, but there's no easy way to make all your floats be of
this class:
    class MyFloat(float):
        def __cmp__(a, b):
            eps = 1e-5
            if abs(b-a) < eps:
                return 0
            return super(MyFloat, a).__cmp__(b)
            
>>> x = MyFloat(0.5)
>>> y = MyFloat(x + .5**53)
>>> x==y
1
>>> float(x) == float(y)
0
>>> z = MyFloat(x + 1e-3)
>>> x==z
0

Of course, this approach is still fraught with danger:
>>> w = MyFloat(x + 7e-6) # just more than eps/2
>>> v = MyFloat(w + 7e-6) # just more than eps/2
>>> x==w, w==v, v==x
(1, 1, 0)

Jeff




More information about the Python-list mailing list