Неточность при операции с Decimal и дробью в периоде

Я пробую сложить числа наподобие 0,7 и 1/3:

print(Decimal(0.7)+Decimal(1/3))

но при сложении этих чисел выводит 1.033333333333333288924412348. Как это исправить, если я не могу использовать округление, так как планируется проект наподобие калькулятора?


Ответы (1 шт):

Автор решения: CrazyElf

Это неточность не Decimal, а неточность встроенных чисел с плавающей точкой самого Питона, которые вы передаёте в конструктор Decimal, это 0.7 и 1/3, которые уже неточно передаются в Decimal.

Кстати, есть полезный приём, который не даст вам в дальнейшем делать такие ошибки (не даст вам смешивать типыfloat и Decimal):

from decimal import getcontext, FloatOperation, Decimal

c = getcontext()
c.traps[FloatOperation] = True

print(Decimal(0.7)+Decimal(1/3))

Получаем исключение FloatOperation:

---------------------------------------------------------------------------
FloatOperation                            Traceback (most recent call last)
      3 c = getcontext()
      4 c.traps[FloatOperation] = True
----> 5 print(Decimal(0.7)+Decimal(1/3))

FloatOperation: [<class 'decimal.FloatOperation'>]

Меняем на подсказанное в комментариях, чтобы исключить любые операции с встроенными числами с плавающей точкой самого Питона (тут только строки и целые числа, которые мы передаём сразу в конструктор Decimal, так что они не успевают "испортиться"):

print(Decimal('0.7')+Decimal(1)/Decimal(3))

И получаем (с prec по умолчанию 28):

1.033333333333333333333333333
→ Ссылка