decimal
— Десятичная арифметика с фиксированной и плавающей точкой¶
Исходный код: Lib/decimal.py
Модуль decimal
предоставляет поддержку быстрой и корректно округляемой
десятичной арифметики с плавающей точкой. Это предлагает несколько преимуществ
перед типом данных float
:
Десятичная «основана на модели с плавающей точкой, которая была разработана для людей и обязательно включает главный руководящий принцип - компьютеры должны обеспечивать арифметику, которая работает так же, как арифметика, которую люди учат в школе». - отрывок из десятичной арифметической спецификации.
Десятичные числа могут быть представлены точно. Напротив, такие числа, как
1.1
и2.2
, не имеют точных представлений в двоичной плавающей точке. Конечные пользователи обычно не ожидают, что1.1 + 2.2
будет отображаться так же3.3000000000000003
, как и с двоичной плавающей точкой.Точность переносится в арифметику. В десятичной плавающей точке
0.1 + 0.1 + 0.1 - 0.3
точно равен нулю. В двоичной плавающей точке результат равен5.5511151231257827e-017
. Хотя различия близки к нулю, они препятствуют надежному тестированию на равенство и могут накапливать различия. По этой причине в приложениях учета, имеющих инварианты строгого равенства, предпочтительно использовать десятичное число.Модуль decimal включает понятие значительных мест, так что
1.30 + 1.20
является2.50
. Конечный ноль сохраняется для указания значимости. Это обычное представление для денежного применения. Для умножения в подходе «школьная книга» используются все цифры в множителях. Для сущность,1.3 * 1.2
дает1.56
, в то время как1.30 * 1.20
дает1.5600
.В отличие от аппаратных двоичных модулей с плавающей точкой, десятичный модуль имеет изменяемую пользователем точность (значение по умолчанию - 28 разрядов), которая может быть настолько велика, насколько это необходимо для данной задачи:
>>> from decimal import * >>> getcontext().prec = 6 >>> Decimal(1) / Decimal(7) Decimal('0.142857') >>> getcontext().prec = 28 >>> Decimal(1) / Decimal(7) Decimal('0.1428571428571428571428571429')
Как двоичная, так и десятичная плавающая точка реализованы в терминах опубликованных стандартов. В то время как встроенный тип float предоставляет лишь скромную часть своих возможностей, десятичный модуль предоставляет все необходимые части стандарта. При необходимости программист полностью контролирует округление и обработку сигналов. Это включает возможность применения точной арифметики с помощью исключений для блокирования любых неточных операций.
Модуль decimal был разработан для поддержки «без предубеждений, как точной неокругляемой десятичной арифметики (иногда называемой арифметикой с фиксированной точкой), так и округляемой арифметики с плавающей точкой». - отрывок из спецификации десятичной арифметически.
Конструкция модуля сосредоточена вокруг трех понятий: десятичное число, арифметический контекст и сигналы.
Десятичное число является неизменяемым. У него есть знак, цифры коэффициента и
степень. Для сохранения значимости цифры коэффициента не усекают конечные нули.
Десятичные разряды также включают специальные значения, такие как
Infinity
, -Infinity
и NaN
. Стандарт также отличает -0
от
+0
.
Арифметический контекст - точность определяемая средой, правила округления,
пределы экспоненты, флаги, указывающие на результаты операций и
инструменты реализации ловушки, которые определяют, рассматривают ли сигналы как
исключения. Опции округления включают ROUND_CEILING
, ROUND_DOWN
, ROUND_FLOOR
,
ROUND_HALF_DOWN
, ROUND_HALF_EVEN
, ROUND_HALF_UP
, ROUND_UP
и ROUND_05UP
.
Сигналы представляют собой группы исключительных условий, возникающих в процессе
вычисления. В зависимости от потребностей приложения сигналы могут
игнорироваться, рассматриваться как информационные или рассматриваться как
исключения. Сигналы в decimal модуле: Clamped
, InvalidOperation
,
DivisionByZero
, Inexact
, Rounded
, Subnormal
,
Overflow
, Underflow
и FloatOperation
.
Для каждого сигнала имеется флаг и активатор ловушки. При обнаружении сигнала его флаг устанавливается в единицу, тогда, если активатор ловушки установлен в единицу, поднимается исключение. Флаги являются липкими, поэтому пользователю необходимо сбросить их перед мониторингом вычислений.
См.также
- Спецификация общей десятичной арифметики IBM, Общая спецификация десятичной арифметики.
Учебник для быстрого старта¶
Обычное начало использования десятичных чисел начинается с импортирования модуля, рассматривая
текущий контекст с getcontext()
и, при необходимости, устанавливая новый
значения для точности, округления или активацию ловушек:
>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero,
InvalidOperation])
>>> getcontext().prec = 7 # Установить новую точность
Десятичные сущности могут быть построены из целых чисел, строк,
плавающих или кортежей. Построение из целого числа или числа с плавающей точкой
выполняет точное преобразование значение этого целого числа или числа с
плавающей точкой. Десятичные числа включают специальные значения, такие как
NaN
, что означает «Не число», положительное и отрицательное Infinity
и -0
:
>>> getcontext().prec = 28
>>> Decimal(10)
Decimal('10')
>>> Decimal('3.14')
Decimal('3.14')
>>> Decimal(3.14)
Decimal('3.140000000000000124344978758017532527446746826171875')
>>> Decimal((0, (3, 1, 4), -2))
Decimal('3.14')
>>> Decimal(str(2.0 ** 0.5))
Decimal('1.4142135623730951')
>>> Decimal(2) ** Decimal('0.5')
Decimal('1.414213562373095048801688724')
>>> Decimal('NaN')
Decimal('NaN')
>>> Decimal('-Infinity')
Decimal('-Infinity')
Если сигнал FloatOperation
захвачен, случайное смешение десятичных разрядов и
плавающих чисел в конструкторах или сравнение порядка поднимает исключение:
>>> c = getcontext()
>>> c.traps[FloatOperation] = True
>>> Decimal(3.14)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Decimal('3.5') < 3.7
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Decimal('3.5') == 3.5
True
Добавлено в версии 3.3.
Значимость нового десятичного знака определяется исключительно количеством введенных цифр. Точность контекста и округление вступают в действие только во время арифметических операций.
>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')
Если внутренние пределы версии C превышены, строение десятичного числа поднимет
InvalidOperation
:
>>> Decimal("1e9999999999999999999")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
Изменено в версии 3.3.
Децималы хорошо взаимодействуют с большей частью остального Python. Вот небольшой десятичный летающий цирк с плавающей точкой:
>>> data = list(map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()))
>>> max(data)
Decimal('9.25')
>>> min(data)
Decimal('0.03')
>>> sorted(data)
[Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),
Decimal('2.35'), Decimal('3.45'), Decimal('9.25')]
>>> sum(data)
Decimal('19.29')
>>> a,b,c = data[:3]
>>> str(a)
'1.34'
>>> float(a)
1.34
>>> round(a, 1)
Decimal('1.3')
>>> int(a)
1
>>> a * 5
Decimal('6.70')
>>> a * b
Decimal('2.5058')
>>> c % a
Decimal('0.77')
Некоторые математические функции также доступны для Decimal:
>>> getcontext().prec = 28
>>> Decimal(2).sqrt()
Decimal('1.414213562373095048801688724')
>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal('10').ln()
Decimal('2.302585092994045684017991455')
>>> Decimal('10').log10()
Decimal('1')
Метод quantize()
округляет число до фиксированной степени. Этот метод полезен
для монетарных приложений, которые часто округляют результаты до фиксированного
количества мест:
>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')
Как показано выше, функция getcontext()
осуществляет доступ к текущему
контексту и позволяет изменять настройки. Этот подход отвечает потребностям
большинства приложений.
Для более продвинутой работы может быть полезно создать альтернативные контексты
с помощью конструктора Context(). Чтобы сделать альтернативу активной,
используйте функцию setcontext()
.
В соответствии со стандартом модуль decimal
предоставляет два готовых к
использованию стандартных контекста: BasicContext
и ExtendedContext
. Первое особенно
полезно для отладки, так как многие ловушки включены:
>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
>>> setcontext(myothercontext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857142857142857142857142857')
>>> ExtendedContext
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[], traps=[])
>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857143')
>>> Decimal(42) / Decimal(0)
Decimal('Infinity')
>>> setcontext(BasicContext)
>>> Decimal(42) / Decimal(0)
Traceback (most recent call last):
File "<pyshell#143>", line 1, in -toplevel-
Decimal(42) / Decimal(0)
DivisionByZero: x / 0
Контексты также имеют сигнальные флаги для мониторинга исключительных условий,
встречающихся во время вычислений. Флаги остаются установленными до явного
сброса, поэтому лучше очистить флаги перед каждым набором контролируемых
вычислений с помощью метода clear_flags()
:
>>> setcontext(ExtendedContext)
>>> getcontext().clear_flags()
>>> Decimal(355) / Decimal(113)
Decimal('3.14159292')
>>> getcontext()
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[])
Запись flags показывает, что рациональное приближение к Pi
было
округлено (цифры сверх точности контекст были выброшены) и что результат
неточен (некоторые отброшенные цифры были ненулевыми).
Отдельные ловушки устанавливаются с помощью словаря в поле traps
контекста:
>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(0)
Decimal('Infinity')
>>> getcontext().traps[DivisionByZero] = 1
>>> Decimal(1) / Decimal(0)
Traceback (most recent call last):
File "<pyshell#112>", line 1, in -toplevel-
Decimal(1) / Decimal(0)
DivisionByZero: x / 0
Большинство программ регулирует текущий контекст только однажды, в начале
программы. И во многих приложениях данные преобразуются в Decimal
с одним
приведением внутри цикла. С набором контекст и созданными десятичными
числами, большая часть программы управляет данными не иначе, чем с другими
числовыми типами Python.
Объекты Decimal¶
-
class
decimal.
Decimal
(value="0", context=None)¶ Создать новый объект
Decimal
на основе value.value может быть целым числом, строка, кортежем,
float
или другим объектомDecimal
. Если не передан value, возвращаетсяDecimal('0')
. Если value является строкой, она должна соответствовать десятичному числовому синтаксису строки после удаления начальных и конечных символов пробела, а также знаков подчеркивания:sign ::= '+' | '-' digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' indicator ::= 'e' | 'E' digits ::= digit [digit]... decimal-part ::= digits '.' [digits] | ['.'] digits exponent-part ::= indicator [sign] digits infinity ::= 'Infinity' | 'Inf' nan ::= 'NaN' [digits] | 'sNaN' [digits] numeric-value ::= decimal-part [exponent-part] | infinity numeric-string ::= [sign] numeric-value | [sign] nan
Другие десятичные цифры Юникода также разрешены там, где
digit
отображается выше. К ним относятся десятичные цифры из различных других алфавитов (например, арабско-индские и деванагарские цифры) вместе с полноширотными цифрами'\uff10'
-'\uff19'
.Если value является
tuple
, у него должны быть три компонента, знак (0
для положительного или1
для отрицательного),tuple
цифр и целое число. Например,Decimal((0, (1, 4, 1, 4), -3))
возвращаетDecimal('1.414')
.Если value является
float
, двоичный значение с плавающей точкой без потерь преобразуется в его точный десятичный эквивалент. Это преобразование часто требует 53 или более цифр точности. Например,Decimal(float('1.1'))
преобразует вDecimal('1.100000000000000088817841970012523233890533447265625')
.Точность context не влияет на количество сохраняемых цифр. Это определяется исключительно количеством цифр в value. Например,
Decimal('3.00000')
записывает все пять нулей, даже если точность контекста равна только трем.Цель аргумента context - определить, что делать, если value является неправильной строкой. Если контекст ловит
InvalidOperation
, возникает исключение; иначе конструктор возвращает новое десятичное число с значениеNaN
.После построения объекты
Decimal
являются неизменяемыми.Изменено в версии 3.2: Теперь аргументу конструктора разрешено быть
float
сущностью.Изменено в версии 3.3:
float
аргументы вызывают исключение, если задана ловушкаFloatOperation
. По умолчанию ловушка выключена.Изменено в версии 3.6: Для группировки допускаются подчеркивания, как и для литералов с интегральной и плавающей точкой в коде.
Decimal объекты с плавающей точкой содержат много общих свойств с другими встроенными числовыми типами, такими как
float
иint
. Применяются все обычные математические операции и специальные методы. Также, decimal объекты могут быть скопированы, pickled, напечатаны, используемый как ключи словаря, используемый как элементы множества, сравнение, сортировка, и принуждение к другому типу (такому какfloat
илиint
).Существуют небольшие различия между арифметикой десятичных объектов и арифметикой целых чисел и плавающих. Когда оператор остатка
%
применяется к десятичным объектам, знак результата является знаком делимо, а не знаком делителя:>>> (-7) % 4 1 >>> Decimal(-7) % Decimal(4) Decimal('-3')
Оператор целочисленного деления
//
ведет себя аналогично, возвращая целую часть истинного частного (усечение к нулю), а не своего нижнего предела, чтобы сохранить обычное тождествоx == (x // y) * y + x % y
:>>> -7 // 4 -2 >>> Decimal(-7) // Decimal(4) Decimal('-1')
Операторы
%
и//
реализуют операцииremainder
иdivide-integer
(соответственно), как описано в описании.Decimal объекты в арифметических операциях обычно нельзя сочетать с флоатами или сущности
fractions.Fraction
: попытка добавитьDecimal
кfloat
, например, подниметTypeError
. Однако возможно использовать операторов сравнения Python, чтобы сравнитьDecimal
сущностьx
с другим номеромy
. Это позволяет избежать путаницы результатов при проведении сравнений равенства между числами различных типов.Изменено в версии 3.2: Сравнения смешанного типа между
Decimal
сущности и другими числовыми типами теперь полностью поддерживается.Помимо стандартных числовых свойств, decimal объекты с плавающей точкой также имеют ряд специализированных методов:
-
adjusted
()¶ Возвращает скорректированную степень после смещения крайних правых цифр коэффициента до тех пор, пока не останется только ведущая цифра:
Decimal('321e+5').adjusted()
возвращает семь. Используется для определения положения наиболее значимой цифры относительно десятичной точки.
-
as_integer_ratio
()¶ Возвращает пару
(n, d)
целых чисел, которые представляют даннуюDecimal
сущность как дробь, с отрицательным числителем и с положительным знаменателем:>>> Decimal('-3.14').as_integer_ratio() (-157, 50)
Преобразование является точным. Поднимет OverflowError для бесконечностей и CreateError для NaN.
Добавлено в версии 3.6.
-
as_tuple
()¶ Возвращает именованный кортеж представление числа:
DecimalTuple(sign, digits, exponent)
.
-
canonical
()¶ Возвращает каноническую кодировку аргумента. В настоящее время кодировка
Decimal
сущность всегда каноническая, таким образом, эта операция возвращает свой неизменный аргумент.
-
compare
(other, context=None)¶ Сравнение значений двух десятичных сущности.
compare()
возвращает десятичную сущность, и если любой из операндов является NaN, то результатом будет NaN:a or b is a NaN ==> Decimal('NaN') a < b ==> Decimal('-1') a == b ==> Decimal('0') a > b ==> Decimal('1')
-
compare_signal
(other, context=None)¶ Эта операция идентична методу
compare()
, за исключением сигнала NaNs. То есть, если ни один из операндов не является сигнальным NaN, то любой тихий операнд NaN рассматривается как сигнальный NaN.
-
compare_total
(other, context=None)¶ Сравнение двух операнд, используя их абстрактное представление, а не числовые значение. Аналогично методу
compare()
, но результат даёт общий порядок наDecimal
сущности. ДваDecimal
сущности с одним и тем же числовым значение, но разные представления сравниваются неравнозначно в этом порядке:>>> Decimal('12.0').compare_total(Decimal('12')) Decimal('-1')
В общий порядок также включены тихие и сигнальные NaN. Результат этой функции является
Decimal('0')
, если оба операнда имеют одинаковое представление,Decimal('-1')
если первый операнд ниже в общем порядке, чем второй, иDecimal('1')
если первый операнд выше в общем порядке, чем второй операнд. Подробные сведения об общем порядке см. в спецификации.Эта операция не зависит от контекста и является тихой: флаги не изменяются и округление не выполняется. В качестве исключения, версия на языке C может возродить операцию CancelOperation, если второй операнд не может быть преобразован точно.
-
compare_total_mag
(other, context=None)¶ Сравнение двух операндов, используя их абстрактное представление, а не их значение, как в
compare_total()
, но игнорируя знак каждого операнда.x.compare_total_mag(y)
эквивалентноx.copy_abs().compare_total(y.copy_abs())
.Эта операция не зависит от контекста и является тихой: флаги не изменяются и округление не выполняется. В качестве исключения, версия на языке C может возродить операцию CancelOperation, если второй операнд не может быть преобразован точно.
-
conjugate
()¶ Просто возвращает себя, этот метод только для соответствия десятичной спецификации.
-
copy_abs
()¶ Возвращает абсолютное значение аргумента. Эта операция не зависит от контекста и является тихой: флаги не изменяются и округление не выполняется.
-
copy_negate
()¶ Возвращает отрицание аргумента. Эта операция не зависит от контекста и является тихой: флаги не изменяются и округление не выполняется.
-
copy_sign
(other, context=None)¶ Возвращает копию первого операнда со знаком, равным знаку второго операнда. Например:
>>> Decimal('2.3').copy_sign(Decimal('-1.5')) Decimal('-2.3')
Эта операция не зависит от контекста и является тихой: флаги не изменяются и округление не выполняется. В качестве исключения, версия на языке C может возродить операцию CancelOperation, если второй операнд не может быть преобразован точно.
-
exp
(context=None)¶ Возвращает значение (естественной) экспоненциальной функции
e**x
при заданном числе. Результат правильно округляется с использованием режима округленияROUND_HALF_EVEN
.>>> Decimal(1).exp() Decimal('2.718281828459045235360287471') >>> Decimal(321).exp() Decimal('2.561702493119680037517373933E+139')
-
from_float
(f)¶ Метод класса, преобразующий плавающую точку в десятичное число.
Примечание Decimal.from_float(0.1) не совпадает с Decimal(„0.1“). Поскольку 0.1 не является точно представимым в двоичной плавающей точке, значение сохраняется как ближайший представимый значение, который является 0x1.999999999999ap-4. Этот эквивалент значение в десятичном формате равен 0.1000000000000000055511151231257827021181583404541015625.
Примечание
Начиная с Python 3.2,
Decimal
сущность также может быть построена непосредственно изfloat
.>>> Decimal.from_float(0.1) Decimal('0.1000000000000000055511151231257827021181583404541015625') >>> Decimal.from_float(float('nan')) Decimal('NaN') >>> Decimal.from_float(float('inf')) Decimal('Infinity') >>> Decimal.from_float(float('-inf')) Decimal('-Infinity')
Добавлено в версии 3.1.
-
fma
(other, third, context=None)¶ Плавленное умножение-сложение. Возвращает self*other+third без округления промежуточного продукта self*other.
>>> Decimal(2).fma(3, 5) Decimal('11')
-
is_canonical
()¶ Возвращает
True
если аргумент является каноническим иFalse
иначе. В настоящее времяDecimal
сущность всегда канонична, поэтому эта операция всегда возвращаетTrue
.
-
is_finite
()¶ Возвращает
True
если аргумент является конечным числом, иFalse
если аргумент является бесконечностью или NaN.
-
is_infinite
()¶ Возвращает
True
если аргумент является либо положительным, либо отрицательным бесконечностью иFalse
иначе.
-
is_normal
(context=None)¶ Возвращает
True
, если аргумент - конечное обычное число. ВозвращаетFalse
если аргумент равен нулю, субнормали, бесконечности или NaN.
-
is_signed
()¶ Возвращает
True
если аргумент имеет отрицательный знак иFalse
иначе. Обратите внимание, что нули и NaN могут нести знаки.
-
is_zero
()¶ Возвращает
True
если аргумент является (положительным или отрицательным) нулем иFalse
иначе.
-
ln
(context=None)¶ Возвращает натуральный (по основанию е) логарифм операнда. Результат правильно округляется с использованием режима округления
ROUND_HALF_EVEN
.
-
log10
(context=None)¶ Возвращает логарифм по основанию 10 операнда. Результат правильно округляется с использованием режима округления
ROUND_HALF_EVEN
.
-
logb
(context=None)¶ Для ненулевого числа возвращает скорректированную экспоненту своего операнда как
Decimal
сущность. Если операнд равен нулю, тоDecimal('-Infinity')
возвращенныйand поднимается флагDivisionByZero
. Если операнд является бесконечностью, то возвращаетсяDecimal('Infinity')
.
-
logical_and
(other, context=None)¶ logical_and()
- логическая операция, которая занимает два логические операнды (см. Логические операнды). В результате получается цифраи
двух операндов.
-
logical_invert
(context=None)¶ logical_invert()
является логической операцией. Результатом является инверсия операнда по цифрам.
-
logical_or
(other, context=None)¶ logical_or()
- логическая операция, которая берет два логических операнда (см. Логические операнды). В результате получается цифраили
два операнда.
-
logical_xor
(other, context=None)¶ logical_xor()
- логическая операция, которая занимает два логических операнда (см. Логические операнды). Результатом является исключительная цифра или два операнда.
-
max
(other, context=None)¶ Подобно
max(self, other)
за исключением того, что правило округления контекста применяется прежде, чем возвратиться и теNaN
значения либо сигнализируются, либо игнорируются (в зависимости от контекста сигнализируюся или замалчиваются).
-
max_mag
(other, context=None)¶ Аналогично методу
max()
, но сравнение выполняется с использованием абсолютной значений операндов.
-
min
(other, context=None)¶ Подобно
min(self, other)
за исключением того, что правило округления контекста применяется прежде, чем возвратиться и теNaN
значения либо сигнализируются, либо игнорируются (в зависимости от контекста сигнализируюся или замалчиваются).
-
min_mag
(other, context=None)¶ Аналогично методу
min()
, но сравнение выполняется с использованием абсолютной значения операндов.
-
next_minus
(context=None)¶ Возвращает большое число, представляемое в данном контекст (или в текущем контексте потока, если не задан контекст), которое меньше заданного операнда.
-
next_plus
(context=None)¶ Возвращает наименьшее число, представляемое в данном контекст (или в текущем контексте потока, если не задан контекст), которое больше заданного операнда.
-
next_toward
(other, context=None)¶ Если два операнда неравны, возвращает число, ближайшее к первому операнду в направлении второго операнда. Если оба операнда численно равны, то возвращает a копия первого операнда со знаком, установленным таким же, как знак второго операнда.
-
normalize
(context=None)¶ Нормализировать число путем удаления крайних правых конечных нулей и преобразования любого результата, равного
Decimal('0')
, вDecimal('0e0')
. Используется для получения канонических значения для атрибуты класса эквивалентности. Например,Decimal('32.100')
иDecimal('0.321000e+2')
нормализуются до эквивалентного значениеDecimal('32.1')
.
-
number_class
(context=None)¶ Возвращает строку описание class операнда. возвращенный значение - один из следующих десяти строк.
"-Infinity"
, что указывает на отрицательную бесконечность операнда."-Normal"
, указывающий, что операнд является отрицательным нормальным числом."-Subnormal"
, указывающий, что операнд является отрицательным и субнормальным."-Zero"
, указывающий, что операнд является отрицательным нулем."+Zero"
, указывающий, что операнд является положительным нулем."+Subnormal"
, указывающий, что операнд является положительным и субнормальным."+Normal"
, указывающий, что операнд является положительным нормальным числом."+Infinity"
, что указывает на положительную бесконечность операнда."NaN"
, указывающий, что операнд является тихим NaN (не число)."sNaN"
, указывающий, что операнд является сигнальным NaN.
-
quantize
(exp, rounding=None, context=None)¶ Возвращает значение равному первому операнду после округления и содержит степень второго операнда.
>>> Decimal('1.41421356').quantize(Decimal('1.000')) Decimal('1.414')
В отличие от других операций, если длина коэффициента после операции квантования будет больше, чем точность, то сигнализируется
InvalidOperation
. Это гарантирует, что, если не существует условия ошибки, квантованный экспонент всегда равен показателю правого операнда.Кроме того, в отличие от других операций, квантование никогда не сигнализирует о Underflow, даже если результат является субнормальным и неточным.
Если степень второго операнда больше степени первого операнда, может потребоваться округление. В этом случае режим округления определяется аргументом
rounding
, если он задан, иначе заданным аргументомcontext
; если ни один из аргументов не задан, используется режим округления текущего контекстного потока.Возвращается ошибка всякий раз, когда, получающаяся экспонента больше, чем
Emax
или меньше, чемEtiny
.
-
radix
()¶ Возвращает
Decimal(10)
, радикс (основание), в котором классDecimal
выполняет всю арифметику. Включено для совместимости со спецификацией.
-
remainder_near
(other, context=None)¶ Возвращает остаток от деления self на other. Это отличается от
self % other
тем, что знак остатка выбран таким образом, чтобы минимизировать его абсолютную значение. Точнее, возвращает значение естьself - n * other
гдеn
- целое число, ближайшее к точному значениеself / other
, и если два целых одинаково близки, то выбирается чётное.Если результат равен нулю, то его знак будет знаком self.
>>> Decimal(18).remainder_near(Decimal(10)) Decimal('-2') >>> Decimal(25).remainder_near(Decimal(10)) Decimal('5') >>> Decimal(35).remainder_near(Decimal(10)) Decimal('-5')
-
rotate
(other, context=None)¶ Возвращает результат поворота цифр первого операнда на величину, заданную вторым операндом. Второй операнд должен быть целым числом в диапазоне - точности через точность. Абсолютная значение второго операнда даёт количество мест для поворота. Если второй операнд положительный, то вращение влево; в противном случае поворот осуществляется вправо. Коэффициент первого операнда при необходимости заполняется нулями до точности длины. Знак и экспонента первого операнда неизменны.
-
same_quantum
(other, context=None)¶ Проверка, имеет ли self и другой ту же экспоненту или являются ли оба
NaN
.Эта операция не зависит от контекста и является тихой: флаги не изменяются и округление не выполняется. В качестве исключения, версия на языке C может возродить операцию CancelOperation, если второй операнд не может быть преобразован точно.
-
scaleb
(other, context=None)¶ Возвращает первый операнд с экспонентой, регулируемый вторым. Эквивалентно, возвращает первый операнд, умноженный на
10**other
. Второй операнд должен быть целым числом.
-
shift
(other, context=None)¶ Возвращает результат сдвига цифр первого операнда на величину, заданную вторым операндом. Второй операнд должен быть целым числом в диапазоне - точности. Абсолютная значение второго операнда даёт количество мест для сдвига. Если второй операнд положительный, то сдвиг влево; в противном случае смещение происходит вправо. Цифры, сдвинутые в коэффициент, являются нулями. Знак и экспонента первого операнда неизменны.
-
sqrt
(context=None)¶ Возвращает квадратный корень аргумента до полной точности.
-
to_eng_string
(context=None)¶ Преобразовать в строку, используя инженерную нотацию, если требуется степень.
Инженерная нотация содержит степень, кратную 3. Это может оставить до 3 цифр слева от десятичного знака и может потребовать добавления одного или двух конечных нулей.
Например, этот метод преобразует
Decimal('123E+1')
вDecimal('1.23E+3')
.
-
to_integral
(rounding=None, context=None)¶ Идентичен методу
to_integral_value()
. Имяto_integral
сохранено для совместимости со старыми версиями.
-
to_integral_exact
(rounding=None, context=None)¶ Округление к ближайшему целому числу, сигнализируя о
Inexact
илиRounded
как соответствующих, если округление происходит. Режим округления определяется параметромrounding
и еще переданнымcontext
. Если никакой параметр не передан тогда, тогда используется режим округления текущего контекста.
-
Объекты контекста¶
Контексты - это среды для арифметических операций. Они управляют точностью, устанавливают правила округления, определяют, какие сигналы рассматриваются как исключения и ограничивают диапазон для экспонент.
Каждый поток содержит свой собственный текущий контекст, доступ к которому
или изменение которого осуществляется с помощью функций getcontext()
и
setcontext()
:
-
decimal.
getcontext
()¶ Возвращает текущее контекст для активного потока.
-
decimal.
setcontext
(c)¶ Установить текущий контекст для активного потока в c.
Вы можете также использовать with
инструкция и функцию localcontext()
, чтобы
временно изменить активный контекст.
-
decimal.
localcontext
(ctx=None)¶ Диспетчер возвращает контекст, который установит текущее контекст для активного поток в копию ctx при входе в with-инструкция и восстановит предыдущее контекст при выходе из with-инструкции. Если контекст не определен, используется копия текущего контекста.
Например, следующий код устанавливает текущую десятичную точность в 42 места, выполняет вычисление и затем автоматически восстанавливает предыдущий контекст:
from decimal import localcontext with localcontext() as ctx: ctx.prec = 42 # Выполнить высокую точность вычислений s = calculate_something() s = +s # Округлить конечный результат до точности по умолчанию
Новые контексты также могут быть созданы с помощью конструктора Context
,
описанного ниже. Кроме того, модуль предоставляет три предварительно созданных
контекста:
-
class
decimal.
BasicContext
¶ Стандартный контекст, определяемый общей десятичной арифметической спецификацией. Точность устанавливается равной девяти. Округление установлено в
ROUND_HALF_UP
. Все флаги очищены. Все ловушки включены (рассматриваются как исключения), кромеInexact
,Rounded
иSubnormal
.Поскольку многие ловушки включены, этот контекст полезен для отладки.
-
class
decimal.
ExtendedContext
¶ Стандартный контекст, определенный общей десятичной арифметической спецификацией. Точность устанавливается равной девяти. Округление установлено в
ROUND_HALF_EVEN
. Все флаги очищены. Ловушки не включены (чтобы исключения не возникали во время вычислений).Поскольку ловушки отключены, этот контекст полезен для приложений, которые предпочитают получить в результате значение
NaN
илиInfinity
вместо того, чтобы поднять исключения. Это позволяет приложению завершить запуск в присутствии условий, которые в противном случае остановят программу.
-
class
decimal.
DefaultContext
¶ Этот контекст используется конструктором
Context
как прототип для новых контекстов. Изменение поля (также и точности) приводит к изменению значения по умолчанию для новых контекстов, созданных конструкторомContext
.Этот контекст наиболее полезен в многопоточных средах. Изменяя одно из полей, прежде чем потоки начаты, реализует эффект настройки общесистемных умолчаний. Изменение полей после того, как потоки начались, не рекомендуется, поскольку это потребовало бы, чтобы синхронизация потоков предотвратила условия гонки.
В однопоточных средах предпочтительно вообще не использовать этот контекст. Вместо этого просто создайте контексты явно, как описано ниже.
Значения по умолчанию -
prec
= :const:28,rounding
= :const:ROUND_HALF_EVEN, и включить ловушки дляOverflow
,InvalidOperation
иDivisionByZero
.
В дополнение к трем предоставленным контекстам можно создавать новые контексты с
помощью конструктора Context
.
-
class
decimal.
Context
(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)¶ Создание нового контекста. Если поле не указано или является
None
, значения по умолчанию копируются изDefaultContext
. Если поле flags не указано или имеет значениеNone
, все флаги очищаются.prec - целое число в диапазоне [
1
,MAX_PREC
], которое задает точность для арифметических операций в контекста.Параметр rounding является одной из констант, перечисленных в разделе Режимы округления.
В полях traps и flags перечислены любые сигналы, которые должны быть установлены. Как правило, новые контексты должны только устанавливать ловушки и оставлять флаги чистыми.
Поля Emin и Emax являются целыми числами, задающими внешние пределы, допустимые для экспонент. Emin должен быть в диапазоне [
MIN_EMIN
,0
], Emax в диапазоне [0
,MAX_EMAX
].Поле capitals должно быть
0
или1
(по умолчанию). Если установлено значение1
, экспоненты печатаются с помощью прописнойE
; иначе строчнойe
- используется:Decimal('6.02e+23')
.Поле clamp содержит значение
0
(по умолчанию) или1
. Если установлено в1
, экспонентаe
Decimal
сущность представляется в этом контексте строго ограничен диапазономEmin - prec + 1 <= e <= Emax - prec + 1
. Если clamp0
, то держится более слабое условие: скорректированная экспонентаDecimal
сущность составляет максимумEmax
. Когда clamp равно1
, большое нормальное число, где это возможно, будет иметь уменьшенную степень и соответствующее количество нулей, добавленных к его коэффициенту, чтобы соответствовать ограничениям экспоненты; это сохраняет значение числа, но теряет информацию о значимых конечных нулях. Например:>>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999') Decimal('1.23000E+999')
clamp значение
1
допускает совместимость с форматами десятичного обмена фиксированной ширины, заданными в IEEE 754.Класс
Context
определяет несколько методов общего назначения, а также большое количество методов для выполнения арифметики непосредственно в данном контекста. Кроме того, для каждого из описанных выше способовDecimal
(за исключением методовadjusted()
иas_tuple()
) существует соответствующий методContext
. Например, дляContext
сущностиC
иDecimal
сущностиx
,C.exp(x)
эквивалентноx.exp(context=C)
. Каждый методContext
принимает целое число Python (сущностьint
) где угодно, что принять Decimal сущность.-
clear_flags
()¶ Сбрасывает все флаги в
0
.
-
clear_traps
()¶ Сбрасывает все ловушки в
0
.Добавлено в версии 3.3.
-
copy
()¶ Возвращает дубликат контекста.
-
copy_decimal
(num)¶ Возвращает из копии Decimal сущности в num.
-
create_decimal
(num)¶ Создает новую Decimal сущность из num, но с использованием self в качестве контекста. В отличие от конструктора
Decimal
, к преобразованию применяются точность контекста, метод округления, флаги и ловушки.Это полезно, поскольку константы часто задаются с большей точностью, чем требуется приложению. Другое преимущество состоит в том, что округление сразу же устраняет непреднамеренные эффекты от цифр, превышающих текущую точность. В следующем примере использование неокругленных входных данных означает, что добавление нуля к сумме может изменить результат:
>>> getcontext().prec = 3 >>> Decimal('3.4445') + Decimal('1.0023') Decimal('4.45') >>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023') Decimal('4.44')
Этот метод реализует в to-number операцию спецификации IBM. Если аргумент - строка, никакой лидирующий или завершающего пробела или подчеркивания не разрешены.
-
create_decimal_from_float
(f)¶ Создание новой Decimal сущности из плавающего f, но округление с использованием self в качестве контекста. В отличие от метода класса
Decimal.from_float()
, к преобразованию применяется точность контекста, метод округления, флаги и ловушки.>>> context = Context(prec=5, rounding=ROUND_DOWN) >>> context.create_decimal_from_float(math.pi) Decimal('3.1415') >>> context = Context(prec=5, traps=[Inexact]) >>> context.create_decimal_from_float(math.pi) Traceback (most recent call last): ... decimal.Inexact: None
Добавлено в версии 3.1.
-
Etiny
()¶ Возвращает значение, равное
Emin - prec + 1
, которое является минимальной экспонентой значения для субнормальных результатов. Когда происходит переполнение экспонента устанавливается вEtiny
.
-
Etop
()¶ Возвращает значение, равное
Emax - prec + 1
.
Обычный подход к работе с десятичными разрядами заключается в создании
Decimal
сущности и затем применении арифметических операций, которые происходят в пределах текущего контекст для активного потока. Альтернативный подход заключается в использовании методов контекста для расчета в пределах конкретного контекста. Методы аналогичны методам классаDecimal
и кратко пересчитываются здесь.-
abs
(x)¶ Возвращает абсолютное значение x.
-
add
(x, y)¶ Возвращает сумму x и y.
-
canonical
(x)¶ Возвращает тот же десятичный объект x.
-
compare
(x, y)¶ Сравнивает x и y численно.
-
compare_signal
(x, y)¶ Сравнивает значения двух операндов численно.
-
compare_total
(x, y)¶ Сравнивает два операнда, используя их абстрактное представление.
-
compare_total_mag
(x, y)¶ Сравнивает два операнда, используя их абстрактное представление, игнорируя знак.
-
copy_abs
(x)¶ Возвращает копию x со знаком, установленным в 0.
-
copy_negate
(x)¶ Возвращает копию x с инвертированным знаком.
-
copy_sign
(x, y)¶ Копирует знак с y на x.
-
divide
(x, y)¶ Возвращает x делёного на y.
-
divide_int
(x, y)¶ Возвращает x, деленого на y, усеченная до целого числа.
-
divmod
(x, y)¶ Делит два числа и возвращает целую часть результата.
-
exp
(x)¶ Степень „e ** x“.
-
fma
(x, y, z)¶ Возвращает x, умноженное на y, плюс z.
-
is_canonical
(x)¶ Возвращает
True
, если x является каноническим; в противном случае возвращаетFalse
.
-
is_finite
(x)¶ Возвращает
True
, если x является конечным; в противном случае возвращаетFalse
.
-
is_infinite
(x)¶ Возвращает
True
, если x бесконечно; в противном случае возвращаетFalse
.
-
is_nan
(x)¶ Возвращает значение
True
, если x является qNaN или sNaN; в противном случае возвращаетFalse
.
-
is_normal
(x)¶ Возвращает
True
, если x является обычным числом; в противном случае возвращаетFalse
.
-
is_qnan
(x)¶ Возвращает
True
, если x является тихим NaN; в противном случае возвращаетFalse
.
-
is_signed
(x)¶ Возвращает
True
, если x является отрицательным; в противном случае возвращаетFalse
.
-
is_snan
(x)¶ Возвращает значение
True
, если x является сигнальным NaN; в противном случае возвращаетFalse
.
-
is_subnormal
(x)¶ Возвращает
True
, если x является субнормальной; в противном случае возвращаетFalse
.
-
is_zero
(x)¶ Возвращает
True
, если x равен нулю; в противном случае возвращаетFalse
.
-
ln
(x)¶ Возвращает натуральный (по основанию e) логарифм x.
-
log10
(x)¶ Возвращает логарифм x по основанию 10.
-
logb
(x)¶ Возвращает степень величины MSD операнда.
-
logical_and
(x, y)¶ Применяет логическую операцию and между цифрами каждого операнда.
-
logical_invert
(x)¶ Инвертирует все цифры в x.
-
logical_or
(x, y)¶ Применяет логическую операцию or между цифрами каждого операнда.
-
logical_xor
(x, y)¶ Применяет логическую операцию xor между цифрами каждого операнда.
-
max
(x, y)¶ Сравнивает два значения численно и возвращает максимум.
-
max_mag
(x, y)¶ Сравнивает значения численно с их игнорируемым знаком.
-
min
(x, y)¶ Сравнивает два значения численно и возвращает минимум.
-
min_mag
(x, y)¶ Сравнивает значения численно с их игнорируемым знаком.
-
minus
(x)¶ Минус соответствует унарному префиксу минус оператор в Python.
-
multiply
(x, y)¶ Возвращает умножение x и y.
-
next_minus
(x)¶ Возвращает наибольшее представимое число, меньшее чем x.
-
next_plus
(x)¶ Возвращает наименьшее представимое число, превышающее x.
-
next_toward
(x, y)¶ Возвращает число, наиболее близкое к x, в направлении к y.
-
normalize
(x)¶ Сводит x к простейшей форме.
-
number_class
(x)¶ Возвращает указание класса x.
-
plus
(x)¶ Плюс соответствует унарному префиксу плюс оператор в Python. Эта операция применяет точность контекста и округления, поэтому она не является операцией идентификации.
-
power
(x, y, modulo=None)¶ Возвращает
x
в степениy
, уменьшенное по модулюmodulo
, если передано.С двумя аргументами вычислит
x**y
. Еслиx
отрицательный, тоy
должен быть интегральным. Результат будет неточным, еслиy
не является интегральным и результат является конечным и может быть выражен точно в «точности» цифр. Используется режим округления из контекста. Результаты всегда правильно округляются в Python версии.Decimal(0) ** Decimal(0)
приводит кInvalidOperation
, а еслиInvalidOperation
не захватывается, то даетDecimal('NaN')
.Изменено в версии 3.3: C одуль вычисляет
power()
с точки зрения правильно округленных функцийexp()
иln()
. Результат четко определен, но только «почти всегда правильно округлен».С тремя аргументами вычислить
(x**y) % modulo
. Для формы с тремя аргументами хранятся следующие ограничения для аргументов:- все три аргумента должны быть интегральными,
y
должен быть неотрицательным,- по крайней мере один из
x
илиy
должен быть отличным от нуля modulo
, должно быть отличным от нуля и содержать больше цифр „точности“
Значение, следующее из
Context.power(x, y, modulo)
, равено значению, которое было бы получено, вычислив(x**y) % modulo
с неограниченной точностью, но вычислен более эффективно. Экспонента результата равна нулю, независимо от степенейx
,y
иmodulo
. Результат всегда точный.
-
quantize
(x, y)¶ Возвращает значение, равный x (округленный), имеющий степень y.
-
radix
()¶ Возвращает 10, так как это Decimal,:)
-
remainder
(x, y)¶ Возвращает остаток от целочисленного деления.
Знак результата, если он ненулевой, совпадает с знаком исходного делимого.
-
remainder_near
(x, y)¶ Возвращает
x - y * n
, где n - целое число, ближайшее к точному значениюx / y
(если результат 0, то его знаком будет знак x).
-
rotate
(x, y)¶ Возвращает повернутую копию x, y раз.
-
same_quantum
(x, y)¶ Возвращает значение
True
, если два операнда имеют одинаковую степень.
-
scaleb
(x, y)¶ Возвращает первый операнд после добавления второго значение его exp.
-
shift
(x, y)¶ Возвращает сдвинутую копию x, y раз.
-
sqrt
(x)¶ Квадратный корень неотрицательного числа для точности контекста.
-
subtract
(x, y)¶ Возвращает разницу между x и y.
-
to_eng_string
(x)¶ Преобразовать в строку, используя инженерную нотацию, если требуется степень.
У инженерной нотации должна быть степень, кратную 3. Это может оставить до 3 цифр слева от десятичного знака и может потребовать добавления одного или двух конечных нулей.
-
to_integral_exact
(x)¶ Округление до целого числа.
-
to_sci_string
(x)¶ Преобразует число в строку, используя научную нотацию.
-
Константы¶
Константы в этом разделе относятся только к модулю C. Они также включены в чистую Python версию для совместимости.
32-bit | 64-bit | |
---|---|---|
|
425000000 |
999999999999999999 |
|
425000000 |
999999999999999999 |
|
-425000000 |
-999999999999999999 |
|
-849999999 |
-1999999999999999997 |
-
decimal.
HAVE_THREADS
¶ Значение
True
. Устарел, потому что Python теперь всегда реализует потоки.
Не рекомендуется, начиная с версии 3.9.
-
decimal.
HAVE_CONTEXTVAR
¶ Значение по умолчанию является
True
. Если Python скомпилирован--without-decimal-contextvar
, версия C использует поточнолокальный, а не корутинлокальный контекст, и значение являетсяFalse
. Это несколько быстрее в некоторых вложенных сценариях контекста.
Добавлено в версии 3.9: backported to 3.7 and 3.8
Режимы округления¶
-
decimal.
ROUND_CEILING
¶ Округление к
Infinity
.
-
decimal.
ROUND_DOWN
¶ Округление по направлению к нулю.
-
decimal.
ROUND_FLOOR
¶ Округление к
-Infinity
.
-
decimal.
ROUND_HALF_DOWN
¶ Округление до ближайшего со связями, идущими к нулю.
-
decimal.
ROUND_HALF_EVEN
¶ Округление до ближайшего со связями, идущими к ближайшему четному целому.
-
decimal.
ROUND_HALF_UP
¶ Округление до ближайшего с завязками, уходящими от нуля.
-
decimal.
ROUND_UP
¶ Округление от нуля.
-
decimal.
ROUND_05UP
¶ Округление от нуля, если последняя цифра после округления к нулю была бы равна 0 или 5; в противном случае округляется к нулю.
Сигналы¶
Сигналы представляют собой условия, возникающие во время вычислений. Каждому соответствует один флаг контекста и один активатор ловушки контекста.
Флаг контекста устанавливается при каждом обнаружении условия. После вычисления флаги могут проверяться в информационных целях (для сущность, чтобы определить, было ли вычисление точным). После проверки флагов обязательно очистите все флаги перед началом следующего вычисления.
Если активатор ловушки контекста установлен для сигнала, то это условие
вызывает исключение Python. Например, если задана ловушка DivisionByZero
, то
при обнаружении условия возникает исключение DivisionByZero
.
-
class
decimal.
Clamped
¶ Изменение степени для соответствия ограничениям представления.
Обычно зажим происходит, когда экспонента выходит за пределы
Emin
иEmax
пределов. Если возможно, степень уменьшается до аппроксимации путем добавления нулей к коэффициенту.
-
class
decimal.
DecimalException
¶ Базовый класс для других сигналов и подкласс
ArithmeticError
.
-
class
decimal.
DivisionByZero
¶ Сигнализация деления не бесконечного числа на ноль.
Может происходить с делением, делением по модулю или при увеличении числа до отрицательной степени. Если этот сигнал не захвачен, возвращает
Infinity
или-Infinity
со знаком, определенным входами в расчет.
-
class
decimal.
Inexact
¶ Указывает, что произошло округление, и результат не является точным.
Сигналы при отбрасывании ненулевых цифр при округлении. Возвращается округленный результат. Использование сигнального флага или ловушки, чтобы обнаружить, когда результаты неточны.
-
class
decimal.
InvalidOperation
¶ Выполнена недопустимая операция.
Указывает, что запрошена операция, которая не имеет смысла. Если не попал в ловушку, возвращает значение
NaN
. Возможные причины включают в себя:Infinity - Infinity 0 * Infinity Infinity / Infinity x % 0 Infinity % x sqrt(-x) and x > 0 0 ** 0 x ** (non-integer) x ** Infinity
-
class
decimal.
Overflow
¶ Числовое переполнение.
Указывает, что степень больше чем
Emax
после округления. Если результат не захвачен, то он зависит от режима округления, либо от перемещения внутрь до наибольшего представляемого конечного числа, либо от округления наружу доInfinity
. В любом случаеInexact
иRounded
также сигнализируются.
-
class
decimal.
Rounded
¶ Округление произошло, хотя информация, возможно, не была потеряна.
Сигнализируется всякий раз, когда округление отбрасывает цифры; даже если эти цифры равны нулю (например, округление
5.00
до5.0
). Если не захвачен, возвращает результат без изменений. Этот сигнал используется, чтобы обнаружить потерю значимых цифр.
-
class
decimal.
Subnormal
¶ Степень была ниже, чем
Emin
до округления.Возникает, когда результат операции является субнормальным (степень слишком мала). Если не захвачен, возвращает результат без изменений.
-
class
decimal.
Underflow
¶ Численный нижний поток с результатом, округленным до нуля.
Возникает при смещении субнормального результата к нулю путем округления.
Inexact
иSubnormal
также сигнализируются.
-
class
decimal.
FloatOperation
¶ Обеспечение более строгой семантики при смешивании плавающих и десятичных разрядов.
Если сигнал не захвачен (по умолчанию), смешение плавающих и десятичных разрядов допускается в конструкторе
Decimal
,create_decimal()
и во всех операторах сравнения. И преобразование, и сравнение точны. Любое возникновение смешанной операции фиксируется без необходимости путем установкиFloatOperation
в флагах контекста. Явные преобразования с помощьюfrom_float()
илиcreate_decimal_from_float()
не устанавливают флаг.В противном случае (сигнал захвачен) молчаливы только сравнения равенства и явные преобразования. Все остальные смешанные операции поднимают
FloatOperation
.
В следующей таблице представлена иерархия сигналов:
exceptions.ArithmeticError(exceptions.Exception)
DecimalException
Clamped
DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
Inexact
Overflow(Inexact, Rounded)
Underflow(Inexact, Rounded, Subnormal)
InvalidOperation
Rounded
Subnormal
FloatOperation(DecimalException, exceptions.TypeError)
Заметки о плавающей точке¶
Уменьшение погрешности округления с повышенной точностью¶
Использование десятичной плавающей точки устраняет ошибку десятичного
представления (позволяя представить 0.1
точно); однако некоторые операции
могут по-прежнему вызывать ошибку округления, когда ненулевые цифры превышают
фиксированную точность.
Влияние ошибки округления может быть усилено сложением или вычитанием почти компенсирующих величин, приводящих к потере значимости. Кнут приводит два поучительных примера, когда округленная арифметика с плавающей точкой с недостаточной точностью вызывает распад ассоциативных и распределительных свойств сложения:
# Примеры из Получисловые алгоритмы, раздел 4.2.2.
>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 8
>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w
Decimal('9.5111111')
>>> u + (v + w)
Decimal('10')
>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w)
Decimal('0.01')
>>> u * (v+w)
Decimal('0.0060000')
Модуль decimal
позволяет восстановить идентичность, достаточно расширяя
точность, чтобы избежать потери значимости:
>>> getcontext().prec = 20
>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w
Decimal('9.51111111')
>>> u + (v + w)
Decimal('9.51111111')
>>>
>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w)
Decimal('0.0060000')
>>> u * (v+w)
Decimal('0.0060000')
Специальные значения¶
Система чисел для модуля decimal
предоставляет специальные значения
включая NaN
, sNaN
, -Infinity
, Infinity
, и два ноля,
+0
и -0
.
Бесконечности можно построить непосредственно с помощью: Decimal('Infinity')
. Кроме
того, они могут возникать при делении на ноль, когда сигнал DivisionByZero
не
захватывался. Аналогично, когда сигнал Overflow
не захвачен, бесконечность может
быть результатом округления за пределы наибольшего представляемого числа.
Бесконечности являются знаковыми (аффинными) и могут быть используемы в арифметических операциях, где они рассматриваются как очень большие, неопределённые числа. Для сущность добавление константы к бесконечности даёт ещё один бесконечный результат.
Некоторые операции являются неопределенными и возвращает NaN
или, если
сигнал InvalidOperation
захвачен, вызывают исключение. Например, 0/0
возвращает NaN
, что означает «не число». Это разнообразие NaN
является тихим и, после создания, будет проходить через другие вычисления всегда
приводит к другой NaN
. Это поведение может быть полезно для ряда
вычислений, у которых иногда есть недостающие исходные данные — это позволяет
расчетам продолжаться при пометке конкретных результатов как недопустимых.
Вариант - sNaN
, который сигнализирует вместо того, чтобы остаться тихим
после каждой операции. Это полезное возвращаемое значение, когда недопустимый
результат должен прервать расчет для специальной обработки.
Поведение операторов сравнения Python’а может быть немного странным,
когда речь идет о NaN
. Тест на равенство, где один из операндов - тихий
или сигнальный NaN
всегда, возвращает False
(делая Decimal('NaN')==Decimal('NaN')
), в
то время как тест на неравенство всегда возвращает True
. Попытка сравнения
двух десятичных разрядов с использованием любого из операторов <
,
<=
, >
или >=
поднимет сигнал InvalidOperation
, если
операнд является NaN
, и возвращает False
, если этот сигнал не
захвачен. Обратите внимание, что общая десятичная арифметическая спецификация не
определяет поведение прямых сравнений; эти правила для сравнения с участием
NaN
были взяты из стандарта IEEE 854 (см. таблицу 3 в разделе 5.7).
Чтобы обеспечить строгое соблюдение стандартов, используйте методы compare()
и
compare-signal()
.
Нулевые значения со знаком могут быть получены в результате вычислений, которые не были выполнены. Они сохраняют знак, который был бы получен, если бы расчет был выполнен с большей точностью. Так как их величина равна нулю, как положительные, так и отрицательные нули рассматриваются как равные и их знак является информационным.
В дополнение к двум знаковым нулям, которые различны, но равны, есть различные представления нуля с различной точностью, но эквивалентны в значении. К этому нужно привыкнуть. Для глаза, привыкшего к нормализованные представления с плавающей точкой, не сразу очевидно, что следующий расчет возвращает значение, равное нулю:
>>> 1 / Decimal('Infinity')
Decimal('0E-1000026')
Работа с потоки¶
Функция getcontext()
получает доступ к другому объекту Context
для каждого
потока. Наличие отдельных контекстов потока означает, что потоки
могут вносить изменения (например, getcontext().prec=10
) без вмешательства в другие
потоки.
Аналогично, функция setcontext()
автоматически назначает свою цель текущему
потоку.
Если setcontext()
не был вызван до getcontext()
, то getcontext()
автоматически
создаст новый контекст для использования в текущем потоке.
Новый контекст копируется из прототипа контекста под названием DefaultContext.
Чтобы управлять дефолтами так, чтобы каждый поток использовал те же
значения всюду в приложении, непосредственно измените объект DefaultContext. Это
должно быть сделано перед началом любого потока так, чтобы не было
условия гонки между потоками, вызвав getcontext()
. Например:
# Установить значения по умолчанию для всех потоков, которые будут запущены
DefaultContext.prec = 12
DefaultContext.rounding = ROUND_DOWN
DefaultContext.traps = ExtendedContext.traps.copy()
DefaultContext.traps[InvalidOperation] = 1
setcontext(DefaultContext)
# После этого можно запускать потоки
t1.start()
t2.start()
t3.start()
. . .
Рецепты¶
Вот несколько рецептов, которые служат в качестве полезных функций и которые
демонстрируют способы работы с классом Decimal
:
def moneyfmt(value, places=2, curr='', sep=',', dp='.',
pos='', neg='-', trailneg=''):
"""Преобразовать Decimal в денежную форматированную строку.
places: необходимое количество знаков после запятой
curr: необязательный символ валюты перед знаком (может быть пустым)
sep: дополнительный разделитель группировки (запятая, точка, пробел или пусто)
dp: индикатор десятичной точки (запятая или точка)
указывать только как пустые, когда места нулевые
pos: необязательный знак для положительных чисел: «+», пробел или пусто
neg: необязательный знак для отрицательных чисел: '-', '(', пробел или пусто
trailneg:дополнительный индикатор трейлинг минус:' -',')', пробел или пусто
>>> d = Decimal('-1234567.8901')
>>> moneyfmt(d, curr='$')
'-$1,234,567.89'
>>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
'1.234.568-'
>>> moneyfmt(d, curr='$', neg='(', trailneg=')')
'($1,234,567.89)'
>>> moneyfmt(Decimal(123456789), sep=' ')
'123 456 789.00'
>>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
'<0.02>'
"""
q = Decimal(10) ** -places # 2 places --> '0.01'
sign, digits, exp = value.quantize(q).as_tuple()
result = []
digits = list(map(str, digits))
build, next = result.append, digits.pop
if sign:
build(trailneg)
for i in range(places):
build(next() if digits else '0')
if places:
build(dp)
if not digits:
build('0')
i = 0
while digits:
build(next())
i += 1
if i == 3 and digits:
i = 0
build(sep)
build(curr)
build(neg if sign else pos)
return ''.join(reversed(result))
def pi():
"""Вычислить Пи с текущей точностью.
>>> print(pi())
3.141592653589793238462643383
"""
getcontext().prec += 2 # дополнительные цифры для промежуточных шагов
three = Decimal(3) # заменить "three=3.0" для регулярных флоутов
lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
while s != lasts:
lasts = s
n, na = n+na, na+8
d, da = d+da, da+32
t = (t * n) / d
s += t
getcontext().prec -= 2
return +s # унарный плюс применяется новая точность
def exp(x):
"""Возвращает e, возведенное в степень x. Тип результата соответствует типу ввода.
>>> print(exp(Decimal(1)))
2.718281828459045235360287471
>>> print(exp(Decimal(2)))
7.389056098930650227230427461
>>> print(exp(2.0))
7.38905609893
>>> print(exp(2+0j))
(7.38905609893+0j)
"""
getcontext().prec += 2
i, lasts, s, fact, num = 0, 0, 1, 1, 1
while s != lasts:
lasts = s
i += 1
fact *= i
num *= x
s += num / fact
getcontext().prec -= 2
return +s
def cos(x):
"""Возвращает косинус x, измеренный в радианах.
Аппроксимация рядов Тейлора лучше всего работает при малом значении X.
Для больших значений сначала вычислите x = x % (2 * pi).
>>> print(cos(Decimal('0.5')))
0.8775825618903727161162815826
>>> print(cos(0.5))
0.87758256189
>>> print(cos(0.5+0j))
(0.87758256189+0j)
"""
getcontext().prec += 2
i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 1
while s != lasts:
lasts = s
i += 2
fact *= i * (i-1)
num *= x * x
sign *= -1
s += num / fact * sign
getcontext().prec -= 2
return +s
def sin(x):
"""Возвращает синус x, измеренный в радианах.
Аппроксимация рядов Тейлора лучше всего работает при малом значении X.
Для больших значений сначала вычислите x = x % (2 * pi).
>>> print(sin(Decimal('0.5')))
0.4794255386042030002732879352
>>> print(sin(0.5))
0.479425538604
>>> print(sin(0.5+0j))
(0.479425538604+0j)
"""
getcontext().prec += 2
i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 1
while s != lasts:
lasts = s
i += 2
fact *= i * (i-1)
num *= x * x
sign *= -1
s += num / fact * sign
getcontext().prec -= 2
return +s
Часто задаваемые вопросы по Decimal¶
Вопрос. Громоздко набирать decimal.Decimal('1234.5')
. Есть ли способ минимизировать ввод при
использовании интерактивного интерпретатора?
Ответ. Некоторые пользователи сокращают конструктор только одной буквой:
>>> D = decimal.Decimal
>>> D('1.23') + D('3.45')
Decimal('4.68')
Вопрос. В приложении с фиксированной точкой и двумя десятичными разрядами некоторые входные данные имеют много знаков и требуют округления. Другие не должны иметь избыточных цифр и должны быть проверены. Какие методы должны быть используемы?
Ответ. Метод quantize()
округляется до фиксированного числа десятичных
разрядов. Если задана ловушка Inexact
, она также полезна для проверки:
>>> TWOPLACES = Decimal(10) ** -2 # некоторый Decimal('0.01')
>>> # Округлить до двух знаков
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
>>> # Убедитесь, что число не превышает двух мест
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
...
Inexact: None
Вопрос. Когда у меня есть действительные два места ввода, как мне сохранить этот инвариант во всем приложении?
Ответ. Некоторые операции, такие как сложение, вычитание и умножение на целое
число, автоматически сохраняют фиксированную точку. Другие операции, такие как
деление и нецелочисленное умножение, изменят количество десятичных разрядов и
должны сопровождаться шагом quantize()
:
>>> a = Decimal('102.72') # Начальные значения с фиксированной точкой
>>> b = Decimal('3.17')
>>> a + b # Дополнение сохраняет фиксированную точку
Decimal('105.89')
>>> a - b
Decimal('99.55')
>>> a * 42 # Так же как и целочисленное умножение
Decimal('4314.24')
>>> (a * b).quantize(TWOPLACES) # Должен квантовать нецелое умножение
Decimal('325.62')
>>> (b / a).quantize(TWOPLACES) # И квантовать деление
Decimal('0.03')
При разработке приложений с фиксированной точкой удобно определять функции для
обработки шага quantize()
:
>>> def mul(x, y, fp=TWOPLACES):
... return (x * y).quantize(fp)
>>> def div(x, y, fp=TWOPLACES):
... return (x / y).quantize(fp)
>>> mul(a, b) # Автоматически сохранять фиксированную точку
Decimal('325.62')
>>> div(b, a)
Decimal('0.03')
Вопрос. Есть много способов выразить одно и то же значение. Номера 200
,
200.000
, 2E2
и 02E+4
у всех есть тот же значение в
различной точности. Есть ли способ преобразовать их к единому узнаваемому
каноническому значению?
Ответ. Метод normalize()
сопоставляет все эквивалентные значения одному
представителю:
>>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
>>> [v.normalize() for v in values]
[Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]
Вопрос. Некоторые десятичные значения всегда печатаются с экспоненциальной нотацией. Есть ли способ получить неэкспоненциальное представление?
А. Для некоторых значения экспоненциальная нотация является единственным
способом выражения числа значимых мест в коэффициенте. Например, выражение
5.0E+3
as 5000
сохраняет значение постоянной, но не может показать
значение оригинала в двух местах.
Если приложение не заботится об отслеживании значимости, легко удалить экспонентные и конечные нули, потеряв значимость, но сохранив значение неизменным:
>>> def remove_exponent(d):
... return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')
Вопрос. Есть ли способ преобразовать обычный float в Decimal
?
Ответ. Да, любое двоичное число с плавающей точкой может быть точно выражено как десятичное, хотя точное преобразование может занять больше точности, чем подсказывает интуиция:
>>> Decimal(math.pi)
Decimal('3.141592653589793115997963468544185161590576171875')
Вопрос. В рамках сложных расчетов, как я могу убедиться, что я не получил ложный результат из-за недостаточной точности или аномалий округления.
Ответ. Decimal модуль упрощает проверку результатов. Оптимальным вариантом является повторный запуск вычислений с большей точностью и с различными режимами округления. Широко различающиеся результаты указывают на недостаточную точность, проблемы режима округления, неполноценные входные данные или численно нестабильный алгоритм.
Вопрос. Я заметил, что точность контекста применяется к результатам операций, но не на входы. Есть ли что-то, на что следует обратить внимание при смешивании значений разных точностей?
Ответ. Да. Принцип заключается в том, что все значения считаются точными и поэтому арифметика этих значений. Только результаты округляются. Преимущество для входных данных - это то, что вы печатаете, то и получаете. Недостатком является то, что результаты могут выглядеть странно, если вы забудете, что входные данные не были округлены:
>>> getcontext().prec = 3
>>> Decimal('3.104') + Decimal('2.104')
Decimal('5.21')
>>> Decimal('3.104') + Decimal('0.000') + Decimal('2.104')
Decimal('5.20')
Решением является либо повышение точности, либо принудительное округление входных данных с помощью операции унарного плюса:
>>> getcontext().prec = 3
>>> +Decimal('1.23456789') # унарный плюс запускает округление
Decimal('1.23')
В качестве альтернативы, входные данные можно округлять при создании с помощью
метода Context.create_decimal()
:
>>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal('1.2345')
Вопрос. Быстрая ли реализация CPython для больших чисел?
Ответ. Да. В реализациях CPython и PyPy3 версии C/CFFI Decimal модуля
интегрируют высокоскоростную библиотеку
libmpdec для
произвольной точности правильного округленной десятичной арифметики с плавающей точкой.
libmpdec
использует Карацуба умножение для средних чисел и Теоретическое преобразование числа для очень
больших чисел.
>>> c = getcontext()
>>> c.prec = MAX_PREC
>>> c.Emax = MAX_EMAX
>>> c.Emin = MIN_EMIN
Добавлено в версии 3.3.