fronthem fronthem - 4 months ago 6
Python Question

Why comparing two attributes type `float` and `int` with the same values get `False` in Python?

Let's consider the code below

code:

#!/usr/bin/env python

class Foo():
def __init__(self, b):
self.a = 0.0
self.b = b
def count_a(self):
self.a += 0.1

foo = Foo(1)
for i in range(0, 15):
foo.count_a()
print "a =", foo.a, "b =", foo.b, '"a == b" ->', foo.a == foo.b


Output:

a = 0.2 b = 1 "a == b" -> False
a = 0.4 b = 1 "a == b" -> False
a = 0.6 b = 1 "a == b" -> False
a = 0.8 b = 1 "a == b" -> False
a = 1.0 b = 1 "a == b" -> True
a = 1.2 b = 1 "a == b" -> False
a = 1.4 b = 1 "a == b" -> False
a = 1.6 b = 1 "a == b" -> False
a = 1.8 b = 1 "a == b" -> False
a = 2.0 b = 1 "a == b" -> False
a = 2.2 b = 1 "a == b" -> False
a = 2.4 b = 1 "a == b" -> False
a = 2.6 b = 1 "a == b" -> False
a = 2.8 b = 1 "a == b" -> False
a = 3.0 b = 1 "a == b" -> False


But if I change code on line
11
to
foo = Foo(2)
, the output is turned to be:

a = 0.2 b = 2 "a == b" -> False
a = 0.4 b = 2 "a == b" -> False
a = 0.6 b = 2 "a == b" -> False
a = 0.8 b = 2 "a == b" -> False
a = 1.0 b = 2 "a == b" -> False
a = 1.2 b = 2 "a == b" -> False
a = 1.4 b = 2 "a == b" -> False
a = 1.6 b = 2 "a == b" -> False
a = 1.8 b = 2 "a == b" -> False
a = 2.0 b = 2 "a == b" -> False *
a = 2.2 b = 2 "a == b" -> False
a = 2.4 b = 2 "a == b" -> False
a = 2.6 b = 2 "a == b" -> False
a = 2.8 b = 2 "a == b" -> False
a = 3.0 b = 2 "a == b" -> False


You will see that the output
a = 2.0 b = 2 "a == b" -> False
is totally weird. I think I might misunderstand some concept of OOP in Python. Please explain to me why this unexpected output is happened and how to solve this problem.

Answer

This has nothing to do with Object Orientation - it has to do with the way computers represent floating point numbers internally, and rounding errors. http://floating-point-gui.de/basic/

The Python specificity here is the default string representation of floating point numbers, which will round them at less decimal places than the internal representation for pretty printing.

Although, for people needing correct comparisons, respecting the scale of floating point numbers, Python has introduced a nice mechanism with PEP 485, which added the math.isclose function to the standard library.