2015-02-17 3 views
2

Я знаю, что машины с базой 2 не могут точно представлять определенные значения базы 10, такие как 1/10. Я видел примеры using Python itself. На моей машине:Python, представляющий 1/10

Python 2.7.8 (default, Oct 18 2014, 12:50:18) 
[GCC 4.9.1] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> 1.0/10 
0.1 

Почему это точно представлено здесь?

+4

Потому что это притворство. '>>> '{: .30f}'. Format (1./10)' ''0.100000000000000005551115123126'' –

+1

Связано: [Почему str (float) возвращает больше цифр в Python 3, чем Python 2?] (Http : //stackoverflow.com/questions/25898733/why-does-strfloat-return-more-digits-in-python-3-than-python-2) –

ответ

3

Начиная с Python 2.7 и 3.1, Python отображает числа с плавающей запятой, используя кратчайшее представление, которое при оценке дает одно и то же число с плавающей запятой. От documentation:

Python теперь использует алгоритм Дэвида Гей для нахождения кратчайшего представления с плавающей точкой, который не меняет его значения. Это должно помочь смягчить некоторые путаницы, связанные с двоичными числами с плавающей запятой.

Значимость легко видна с номером 1.1, который не имеет точного эквивалента в двоичной плавающей запятой. Так как нет точного эквивалента, выражение, подобное float('1.1'), оценивается до ближайшего представляемого значения, которое равно 0x1.199999999999ap+0 в шестнадцатеричном виде или 1.100000000000000088817841970012523233890533447265625 в десятичном формате. Это ближайшее значение было и остается в последующих вычислениях с плавающей запятой.

Что нового рядом? Раньше Python использовал простой подход. Значение repr(1.1) было рассчитано как format(1.1, '.17g'), которое оценивалось до '1.1000000000000001'. Преимущество использования 17 цифр состояло в том, что он полагался на гарантии IEEE-754, чтобы гарантировать, что eval(repr(1.1)) будет в оба конца точно до его первоначального значения. Недостаток заключается в том, что многие люди обнаружили, что результат путают (ошибочные внутренние ограничения двоичного представления с плавающей запятой как проблемы с самим Python).

Новый алгоритм для repr(1.1) умнее и возвращает '1.1'. Фактически, он ищет все эквивалентные строковые представления (те, которые хранятся с одним и тем же базовым значением float) и возвращает кратчайшее представление.

Новый алгоритм имеет тенденцию выделять более чистые представления, когда это возможно, но не меняет базовые значения. Таким образом, все еще имеет место 1.1 + 2.2 != 3.3, хотя представления могут предложить другое.

Новый алгоритм зависит от некоторых функций в реализации с плавающей запятой. Если требуемые функции не найдены, старый алгоритм будет по-прежнему использоваться. Кроме того, протоколы расписания текста обеспечивают кросс-платформенную переносимость, используя старый алгоритм.