Почему при сравнении двух атрибутов типа `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
Другие вопросы по тегам