Почему при сравнении двух атрибутов типа `float` и`int` с одинаковыми значениями в Python получается `False`?
Давайте рассмотрим код ниже
код:
#!/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
Выход:
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
Но если я изменю код на линии 11
в foo = Foo(2)
, выход получится:
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
Вы увидите, что на выходе a = 2.0 b = 2 "a == b" -> False
совершенно странно Я думаю, что я мог бы неправильно понять некоторую концепцию ООП в Python. Пожалуйста, объясните мне, почему произошел этот неожиданный вывод и как решить эту проблему.
2 ответа
Это не имеет ничего общего с объектной ориентацией - оно связано с тем, как компьютеры представляют внутренние числа с плавающей запятой, и с ошибками округления. http://floating-point-gui.de/basic/
Специфика Python здесь - это строковое представление по умолчанию чисел с плавающей запятой, которое будет округлять их в меньшем количестве знаков после запятой, чем внутреннее представление для красивой печати.
Хотя для людей, нуждающихся в правильном сравнении и уважении к шкале чисел с плавающей запятой, Python представил хороший механизм с PEP 485, который добавил math.isclose
функция стандартной библиотеки.
Помимо правильного объяснения jsbueno, помните, что Python часто позволяет приводить "базовые типы" к себе.
т.е. str("a") == "a"
Так что, если вам нужен обходной путь в дополнение к причине, просто преобразуйте вашу смесь int/float во все поплавки и протестируйте их.
a = 2.0
b = 2
print "a == b", float(a) == float(b)
выход:
a == b True