Преобразование Python float в Decimal

Python Decimal не поддерживает построение из float; он ожидает, что вам сначала нужно преобразовать float в строку.

Это очень неудобно, так как стандартные строковые форматеры для float требуют указания количества десятичных знаков, а не значимых мест. Поэтому, если у вас есть число, которое может иметь до 15 знаков после запятой, вам нужно отформатировать как десятичное (""%.15f " % my_float), который даст вам мусор на 15-м десятичном месте, если у вас также есть любые значимые цифры до десятичного знака.

может ли кто-нибудь предложить хороший способ преобразования из float в Decimal с сохранением значения по мере ввода пользователем, возможно, ограничивая количество значимых цифр, которые могут быть поддержаны?

7 ответов


Python
"%.15g" % f

или в Python 3.0:

format(f, ".15g")

Python 2.7+, 3.2+

просто передайте поплавок Decimal конструктор напрямую, вот так:

from decimal import Decimal
Decimal(f)

Вы сказали в своем вопросе:

может кто-нибудь предложить хороший способ преобразование из float в Decimal сохранение значения, как пользователь имеет вошел

но каждый раз, когда пользователь вводит значение, оно вводится как строка, а не как float. Вы превращаете его в какой-то поплавок. Преобразуйте его в десятичное число напрямую, и точность не будет потеряна.


Я предлагаю это

>>> a = 2.111111
>>> a
2.1111110000000002
>>> str(a)
'2.111111'
>>> decimal.Decimal(str(a))
Decimal('2.111111')

Python поддерживает десятичное создание из float. Сначала вы просто бросаете его как струну. Но потеря точности не происходит при преобразовании строки. Поплавок, который вы конвертируете, не имеет такой точности в первую очередь. (В противном случае вам не понадобится Decimal)

Я думаю, что путаница здесь в том, что мы можем создавать плавающие литералы в десятичном формате, но как только интерпретатор потребляет этот литерал, внутреннее представление становится плавающим номер точки.


"официальное" строковое представление float задается встроенным repr ():

>>> repr(1.5)
'1.5'
>>> repr(12345.678901234567890123456789)
'12345.678901234567'

вы можете использовать repr() вместо форматированной строки, результат не будет содержать ненужного мусора.


когда вы говорите "сохранение значения, введенного пользователем", почему бы просто не сохранить введенное пользователем значение в виде строки и передать его конструктору Decimal?


"правильный" способ сделать это было зафиксировано в 1990 году Стил и Уайт и PLDI Клингер в 1990 документы.

вы также можете посмотреть на этой Итак, обсуждение Python Decimal, включая мое предложение попробовать использовать что-то вроде фрап рационализировать поплавок.