Я довольно зеленый программист и сейчас изучаю Python.Я дошел до главы 17 в «Учиться мыслить как компьютерный ученый» (Классы и методы), и я только что написал свой первый тестовый документ, который провалился таким образом, которого я действительно не полностью понимаю:
class Point(object):
'''
represents a point object.
attributes: x, y
'''
def ___init___(self, x = 0, y = 0):
'''
>>> point = Point()
>>> point.y
0
>>> point = Point(4.7, 8.2)
>>> point.x
4.7
'''
self.x = x
self.y = y
Второй doctest для __init__
завершается неудачно и возвращает 4.7000000000000002 вместо 4.7.Однако, если я переписываю doctest с оператором «print» следующим образом:
>>> point = Point(4.7, 8.2)
>>> print point.x
4.7
Он работает правильно.
Итак, я прочитал о том, как Python хранит плавающие объекты, и теперь я понимаю, чтоИз-за двоичного представления десятичных чисел причина расхождения заключается в том, что Python хранит 4.7 в виде строки из 1 и 0, которые почти, но не совсем равны 4.7.
Но я не понимаю, почему при вызове «point.x» возвращается 4.7000000000000002, а при вызове «print point.x» возвращается 4.7.При каких других обстоятельствах Python предпочтет округлить, как это происходит с «print»?Как работает это округление?Могут ли эти следы значительных цифр привести к ошибкам в программировании (кроме, очевидно, неудачных тестов)?Может ли отказ обратить внимание на округление создать опасную неоднозначность?
Поскольку это связано с двоичным представлением десятичных чисел, я уверен, что это на самом деле общая проблема CS, а не специфическая для Python,но то, что мне действительно нужно знать прямо сейчас, - это то, что я могу сделать, особенно как программист на Python, чтобы избежать любых связанных с этим проблем и / или заражений багами.
Кроме того, для бонусных баллов есть какой-то другой способ, которымPython может хранить числа с плавающей запятой помимо значений по умолчанию, активируемых строкой типа «a = 4.7»?Я знаю, что есть пакет Decimal, но я не совсем уверен, как он работает.Честно говоря, все эти вещи динамической типизации меня иногда смущают.
Редактировать: Я должен указать, что я использую Python 2.6 (в какой-то момент я хочу использовать NumPy и Biopython)