#python #decimal #precision
#python #десятичный #точность
Вопрос:
from decimal import *
getcontext().prec = 8
print(getcontext(),"n")
x_amount = Decimal(0.025)
y_amount = Decimal(0.005)
test3 = x_amount - y_amount
print("test3",test3)
Вывод:
Контекст (prec= 8, округление = ROUND_HALF_EVEN, Emin=-999999, Emax= 999999, заглавные буквы = 1, зажим = 0, флаги = [], ловушки = [НедейстВительная операция, DivisionByZero, переполнение]) тест3 0.020000000
Почему это возвращает значение ‘test3’ с точностью до 9 знаков после запятой, если точность установлена на 8 в соответствии с примером, упомянутым здесь?
И он изменится на 3 знака после запятой, если я заменю строки 6 и 7 в приведенном выше коде на:
x_amount = Decimal('0.025')
y_amount = Decimal('0.005')
Я использую десятичные дроби в финансовом приложении и нахожу это очень запутанным в отношении преобразований, операций, определения, точности и т.д. Есть ли ссылка, на которую я могу сослаться, чтобы узнать подробности использования десятичных дробей в python?
Комментарии:
1. Не имеет прямого отношения к вашей проблеме, но использование
float
для инициализацииDecimal
всегда неверно. Никогда не инициализируйте aDecimal
из afloat
; это просто воспроизводит неточностьfloat
вDecimal
. Передача astr
— единственный безопасный способ сделать это. Когда я делаю это сstr
помощью и использую строки, которые являются более точными, чемprec
, начальные значения более точны, но все математические операции обеспечивают ожидаемый уровень точности (напримерDecimal("0.025") Decimal("0.123456789")
, getsDecimal('0.14845679')
, который имеет ровно восемь мест точности.2. В случае
Decimal('0.025') - Decimal('0.005')
нет необходимости добавлять до 8 нулей в конце, потому что вы получаете точный результат. Однако десятичное число, инициализированное с плавающей точкой 0.025Decimal('0.0025000000000000000520417042793042128323577344417572021484375')
, равно, поэтому результат обрезается. Однако это не объясняет, почему вы получаете 9 знаков после запятой вместо 8. Кажется, он начинает отсчет с первого ненулевого места, но это всего лишь предположение.
Ответ №1:
Ваш результат верен. prec
указывает, сколько цифр нужно сохранить, начиная с самой значимой ненулевой цифры. Итак, в вашем результате:
test3 0.020000000
^^^^^^^^
цифры, на которые указывают каретки, являются ожидаемыми восемью цифрами, охватываемыми точностью. Причина, по которой вы получаете их все, заключается в том, что использование float
для инициализации Decimal
всегда неверно. Никогда не инициализируйте a Decimal
из a float
; это просто воспроизводит неточность float
в Decimal
(попробуйте print
x_value
и y_value
увидите мусор). Передача a str
— единственный безопасный способ сделать это.
Когда вы делаете это с str
помощью, отдельные Decimal
элементы «знают» последнюю цифру значимой точности, которой они обладают, и она доходит только до третьего знака после запятой, поэтому результат не включает точность за пределами этой точки. Если вы хотите prec
, чтобы сработало ограничение, попробуйте инициализировать один из аргументов с большей точностью, чем prec
, и результат будет округлен до prec
.