Подтвердить что ты не робот

Почему str (float) возвращает больше цифр в Python 3, чем Python 2?

В Python 2.7, repr of float возвращает ближайшее десятичное число до 17 цифр; это достаточно точно, чтобы однозначно идентифицировать каждое возможное значение с плавающей точкой IEEE. str of float работал аналогично, за исключением того, что он ограничивал результат 12 цифрами; для большинства целей это более разумный результат и изолирует вас от небольших различий между двоичным и десятичным представлением.

Демо Python 2: http://ideone.com/OKJtxv

print str(1.4*1.5)
2.1
print repr(1.4*1.5)
2.0999999999999996

В Python 3.2 появляется str и repr возвращает то же самое.

Python 3 demo: http://ideone.com/oAKRsb

print(str(1.4*1.5))
2.0999999999999996
print(repr(1.4*1.5))
2.0999999999999996

Есть ли PEP, который описывает изменение, или какое-либо другое выражение от кого-то ответственного?

4b9b3361

Ответ 1

Нет, нет PEP. Там issue в трекере ошибок и связанное обсуждение в списке рассылки разработчиков Python. Хотя я был ответственен за предложение и реализацию изменений, я не могу утверждать, что это была моя идея: она возникла во время бесед с Guido на EuroPython 2010.

Еще несколько деталей: как уже упоминалось в комментариях, Python 3.1 ввел новый алгоритм для строки repr для float (позже был включен в пакет Python 2, так что он также появляется в Python 2.7). В результате этого нового алгоритма "короткое" десятичное число, введенное в подсказке, имеет соответственно короткое представление. Это устранило одну из существующих причин разницы между str и repr и дало возможность использовать тот же алгоритм как для str, так и для repr. Итак, для Python 3.2 после обсуждения, связанного выше, str и repr были сделаны одинаковыми. Что касается того, почему: он делает язык немного меньше и чище, и при выводе строки удаляется довольно произвольный выбор из 12 цифр. (Выбор 17 цифр, используемых для repr в версиях Python до 2.7, далек от произвольного, между прочим: два разных бинарных двоичных файла IEEE 754 будут иметь различные представления при преобразовании в десятичные числа с 17 значащими цифрами, а 17 - наименьшее целое с этим свойством.)

Помимо простоты, есть некоторые менее очевидные преимущества. Один аспект различия repr versus str, который запутался для пользователей в прошлом, заключается в том, что repr автоматически используется в контейнерах. Так, например, в Python 2.7:

>>> x = 1.4 * 1.5
>>> print x
2.1
>>> print [x]
[2.0999999999999996]

Я уверен, что есть хотя бы один вопрос StackOverflow, спрашивающий об этом явлении где-то: вот один из таких, и другой более поздний. С упрощением, введенным в Python 3.2, мы получаем это вместо:

>>> x = 1.4 * 1.5
>>> print(x)
2.0999999999999996
>>> print([x])
[2.0999999999999996]

который по крайней мере более согласован.

Если вы хотите скрывать неточности, правильный способ сделать это остается неизменным: используйте форматирование строк для точного управления выходным форматом.

>>> print("{:.12g}".format(x))
2.1

Надеюсь, это объяснит некоторые из причин этого изменения. Я не буду утверждать, что это универсально полезно: как вы указываете, старый str имел удобный побочный эффект скрытия неточностей. Но, на мой взгляд (конечно, я предвзятый), это помогает устранить несколько неожиданностей с языка.