Преобразование из float в Decimal в python-2.6: как это сделать и почему они этого не сделали
Прямое преобразование из float в Decimal было реализовано в python-2.7, как в конструкторе Decimal, так и в методе класса Decimal.from_float().
Python-2.6 вместо этого вызывает TypeError, предлагающий сначала преобразовать в строку:
TypeError: Cannot convert float to Decimal. First convert the float to a string
так что это обычное обходное решение:
if sys.version_info < (2, 7):
Decimal.from_float = classmethod(lambda cls, x: cls(str(x)))
Это просто литературный перевод из сообщения об ошибке - и я просто не беспокоюсь о его реализации в конструкторе тоже.
Если это так просто, почему они не внедряли его в первую очередь, а не говорили пользователю сделать это в TypeError? Это лучший доступный метод (и по расширению - тот, который используется в python-2.7 и новее?)
Ответы
Ответ 1
Ваше обходное решение - это не RightWayToDoIt (tm), потому что оно теряет информацию. Способ преобразования без потерь показан в рецепте float_to_decimal()
, показанном в Десятичные часто задаваемые вопросы.
Причина, по которой мы не включили Decimal.from_float в Python 2.6, состоит в том, что мы были консервативны в отношении введения непреднамеренных взаимодействий между двоичными поплавками и десятичными поплавками. По Python 2.7 все это было разработано, и вы можете просто написать Decimal(f)
, где f - двоичный float.
Помимо небольшой неприятности в версии 2.6, я надеюсь, что вам понравится модуль Decimal
Ответ 2
Вероятно, потому что поведение прямого преобразования может быть несовместимым, если вы не знаете несколько сведений о деталях о поплавках. Как указано в документах:
Примечание Decimal.from_float(0.1)
не совпадает с Decimal('0.1')
. Поскольку 0.1
не является точно представимым в двоичной плавающей точке, значение сохраняется как ближайшее представимое значение, которое равно 0x1.999999999999ap-4
. Это эквивалентное значение в десятичном значении 0.1000000000000000055511151231257827021181583404541015625
.
Если вы конвертируете в строку, вы можете контролировать точность, которую хотите использовать, чтобы получить точное преобразование в Decimal
.
Новый метод был введен в Python 2.7 - поэтому его нет в версии 2.6. Новые функции не поддерживаются более старыми версиями.
Ответ 3
В соответствии с 2.7 Что нового документация (выделено мной)
Конверсии между числами с плавающей запятой и строками теперь правильно скруглен на большинстве платформ. Эти преобразования происходят во многих разные места: str() по поплавкам и комплексным числам; поплавок и сложные конструкторы; цифровое форматирование; сериализации и десериализации поплавков и сложных чисел с использованием маршала, маринования и модули json; разбор поплавка и воображаемых литералов в коде Python; и Преобразование десятичных чисел в плавающие.
Итак, хотя они могли сделать это до 2.7, они, по-видимому, не чувствовали себя комфортно, делая это с проблемами округления, которые существовали.