decimal.md
1> **Источник:** https://python-all.ru/3.14/library/decimal.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `decimal` – десятичная арифметика с фиксированной и плавающей запятой89**Исходный код:** [Lib/decimal.py](https://python-all.ru/src/3.14/Lib/decimal.py)1011---1213Модуль `decimal` обеспечивает поддержку быстрой и корректно округлённой десятичной арифметики с плавающей запятой. Он имеет несколько преимуществ перед типом данных [`float`](https://python-all.ru/3.14/library/functions.html#float):1415- Десятичная арифметика «основана на [модели с плавающей запятой](https://python-all.ru/3.14/library/decimal.html), которая разрабатывалась с учётом человеческих потребностей и, безусловно, имеет главный руководящий принцип – компьютеры должны обеспечивать арифметику, работающую так же, как арифметика, которой люди учатся в школе.» – выдержка из спецификации десятичной арифметики.16- Десятичные числа могут быть представлены точно. В отличие от этого, такие числа, как `1.1` и `2.2`, не имеют точного представления в двоичной арифметике с плавающей запятой. Конечные пользователи обычно не ожидают, что `1.1 + 2.2` будет отображаться как `3.3000000000000003`, как это происходит в двоичной арифметике с плавающей запятой.17- Точность распространяется и на арифметику. В десятичной арифметике с плавающей запятой `0.1 + 0.1 + 0.1 - 0.3` точно равно нулю. В двоичной арифметике с плавающей запятой результат равен `5.5511151231257827e-017`. Хотя он близок к нулю, эти различия препятствуют надёжной проверке на равенство и могут накапливаться. По этой причине десятичная арифметика предпочтительна в бухгалтерских приложениях, где существуют строгие инварианты равенства.18- Модуль decimal включает понятие значащих разрядов, так что `1.30 + 1.20` равно `2.50`. Замыкающий ноль сохраняется для указания значимости. Это стандартное представление для финансовых приложений. Для умножения «школьный» подход использует все цифры множителей. Например, `1.3 * 1.2` даёт `1.56`, а `1.30 * 1.20` даёт `1.5600`.19- В отличие от аппаратно реализованной двоичной арифметики с плавающей запятой, модуль decimal имеет настраиваемую точность (по умолчанию 28 знаков), которая может быть сколь угодно большой для данной задачи:2021 ```python22 >>> from decimal import *23 >>> getcontext().prec = 624 >>> Decimal(1) / Decimal(7)25 Decimal('0.142857')26 >>> getcontext().prec = 2827 >>> Decimal(1) / Decimal(7)28 Decimal('0.1428571428571428571428571429')29 ```30- Как двоичная, так и десятичная арифметика с плавающей запятой реализованы в соответствии с опубликованными стандартами. В то время как встроенный тип float предоставляет лишь скромную часть своих возможностей, модуль decimal предоставляет все необходимые части стандарта. При необходимости программист имеет полный контроль над округлением и обработкой сигналов. Это включает возможность принудительного точного выполнения арифметики с помощью исключений для блокировки любых неточных операций.31- Модуль decimal был разработан для поддержки «без каких-либо предпочтений как точной неокруглённой десятичной арифметики (иногда называемой арифметикой с фиксированной запятой), так и округлённой арифметики с плавающей запятой.» – выдержка из спецификации десятичной арифметики.3233Дизайн модуля сосредоточен на трёх концепциях: десятичное число, контекст арифметики и сигналы.3435Десятичное число неизменяемо. Оно имеет знак, цифры коэффициента и показатель степени. Для сохранения значимости цифры коэффициента не отбрасывают замыкающие нули. Десятичные числа также включают специальные значения, такие как `Infinity`, `-Infinity` и `NaN`. Стандарт также различает `-0` и `+0`.3637Контекст арифметики – это окружение, задающее точность, правила округления, ограничения на показатели степени, флаги, указывающие на результаты операций, и активаторы ловушек, которые определяют, обрабатываются ли сигналы как исключения. Варианты округления включают [`ROUND_CEILING`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_CEILING), [`ROUND_DOWN`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_DOWN), [`ROUND_FLOOR`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_FLOOR), [`ROUND_HALF_DOWN`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_DOWN), [`ROUND_HALF_EVEN`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_EVEN), [`ROUND_HALF_UP`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_UP), [`ROUND_UP`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_UP) и [`ROUND_05UP`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_05UP).3839Сигналы – это группы исключительных ситуаций, возникающих в ходе вычислений. В зависимости от потребностей приложения сигналы могут игнорироваться, рассматриваться как информационные или обрабатываться как исключения. Сигналы в модуле decimal: [`Clamped`](https://python-all.ru/3.14/library/decimal.html#decimal.Clamped), [`InvalidOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.InvalidOperation), [`DivisionByZero`](https://python-all.ru/3.14/library/decimal.html#decimal.DivisionByZero), [`Inexact`](https://python-all.ru/3.14/library/decimal.html#decimal.Inexact), [`Rounded`](https://python-all.ru/3.14/library/decimal.html#decimal.Rounded), [`Subnormal`](https://python-all.ru/3.14/library/decimal.html#decimal.Subnormal), [`Overflow`](https://python-all.ru/3.14/library/decimal.html#decimal.Overflow), [`Underflow`](https://python-all.ru/3.14/library/decimal.html#decimal.Underflow) и [`FloatOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.FloatOperation).4041Для каждого сигнала существует флаг и активатор ловушки. Когда сигнал обнаруживается, его флаг устанавливается в единицу, затем, если активатор ловушки установлен в единицу, возбуждается исключение. Флаги сохраняют состояние, поэтому пользователю необходимо сбрасывать их перед мониторингом вычислений.4243> **См. также**44>45> - Спецификация общей десятичной арифметики IBM, [Общая спецификация десятичной арифметики](https://python-all.ru/3.14/library/decimal.html).4647## Краткое руководство4849Обычно работа с десятичными числами начинается с импорта модуля decimal, просмотра текущего контекста с помощью [`getcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.getcontext) и, при необходимости, установки новых значений точности, округления или включённых ловушек:5051```python52>>> from decimal import *53>>> getcontext()54Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,55 capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero,56 InvalidOperation])5758>>> getcontext().prec = 7 # Установить новую точность59```6061Экземпляры Decimal могут быть созданы из целых чисел, строк, чисел с плавающей запятой или кортежей. Создание из целого числа или числа с плавающей запятой выполняет точное преобразование значения этого целого числа или числа с плавающей запятой. Десятичные числа включают специальные значения, такие как `NaN`, которое означает «Не число», положительная и отрицательная `Infinity`, и `-0`:6263```python64>>> getcontext().prec = 2865>>> Decimal(10)66Decimal('10')67>>> Decimal('3.14')68Decimal('3.14')69>>> Decimal(3.14)70Decimal('3.140000000000000124344978758017532527446746826171875')71>>> Decimal((0, (3, 1, 4), -2))72Decimal('3.14')73>>> Decimal(str(2.0 ** 0.5))74Decimal('1.4142135623730951')75>>> Decimal(2) ** Decimal('0.5')76Decimal('1.414213562373095048801688724')77>>> Decimal('NaN')78Decimal('NaN')79>>> Decimal('-Infinity')80Decimal('-Infinity')81```8283Если сигнал [`FloatOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.FloatOperation) отлавливается, случайное смешивание десятичных чисел и чисел с плавающей запятой в конструкторах или при сравнении порядка вызывает исключение:8485```python86>>> c = getcontext()87>>> c.traps[FloatOperation] = True88>>> Decimal(3.14)89Traceback (most recent call last):90 File "<stdin>", line 1, in <module>91decimal.FloatOperation: [<class 'decimal.FloatOperation'>]92>>> Decimal('3.5') < 3.793Traceback (most recent call last):94 File "<stdin>", line 1, in <module>95decimal.FloatOperation: [<class 'decimal.FloatOperation'>]96>>> Decimal('3.5') == 3.597True98```99100Добавлено в версии 3.3.101102Значимость нового Decimal определяется исключительно количеством введённых цифр. Точность контекста и округление вступают в силу только во время арифметических операций.103104```pycon105>>> getcontext().prec = 6106>>> Decimal('3.0')107Decimal('3.0')108>>> Decimal('3.1415926535')109Decimal('3.1415926535')110>>> Decimal('3.1415926535') + Decimal('2.7182818285')111Decimal('5.85987')112>>> getcontext().rounding = ROUND_UP113>>> Decimal('3.1415926535') + Decimal('2.7182818285')114Decimal('5.85988')115```116117Если внутренние ограничения C-версии превышены, создание decimal вызывает [`InvalidOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.InvalidOperation):118119```python120>>> Decimal("1e9999999999999999999")121Traceback (most recent call last):122 File "<stdin>", line 1, in <module>123decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]124```125126Изменено в версии 3.3.127128Decimal хорошо взаимодействует с большей частью остального Python. Вот небольшой десятичный летающий цирк с плавающей запятой:129130```pycon131>>> data = list(map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()))132>>> max(data)133Decimal('9.25')134>>> min(data)135Decimal('0.03')136>>> sorted(data)137[Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),138 Decimal('2.35'), Decimal('3.45'), Decimal('9.25')]139>>> sum(data)140Decimal('19.29')141>>> a,b,c = data[:3]142>>> str(a)143'1.34'144>>> float(a)1451.34146>>> round(a, 1)147Decimal('1.3')148>>> int(a)1491150>>> a * 5151Decimal('6.70')152>>> a * b153Decimal('2.5058')154>>> c % a155Decimal('0.77')156```157158Десятичные числа можно форматировать (с помощью встроенной функции [`format()`](https://python-all.ru/3.14/library/functions.html#format) или [f-строк](https://python-all.ru/3.14/reference/lexical_analysis.html#f-strings)) в нотации с фиксированной запятой или научной нотации, используя тот же синтаксис форматирования (см. [Мини-язык спецификации формата](https://python-all.ru/3.14/library/string.html#formatspec)), что и для встроенного типа [`float`](https://python-all.ru/3.14/library/functions.html#float):159160```pycon161>>> format(Decimal('2.675'), "f")162'2.675'163>>> format(Decimal('2.675'), ".2f")164'2.68'165>>> f"{Decimal('2.675'):.2f}"166'2.68'167>>> format(Decimal('2.675'), ".2e")168'2.68e+0'169>>> with localcontext() as ctx:170... ctx.rounding = ROUND_DOWN171... print(format(Decimal('2.675'), ".2f"))172...1732.67174```175176Также некоторые математические функции доступны для Decimal:177178```python179>>> getcontext().prec = 28180>>> Decimal(2).sqrt()181Decimal('1.414213562373095048801688724')182>>> Decimal(1).exp()183Decimal('2.718281828459045235360287471')184>>> Decimal('10').ln()185Decimal('2.302585092994045684017991455')186>>> Decimal('10').log10()187Decimal('1')188```189190Метод [`quantize()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.quantize) округляет число до заданного показателя степени. Этот метод полезен для финансовых приложений, которые часто округляют результаты до фиксированного количества знаков:191192```python193>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)194Decimal('7.32')195>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)196Decimal('8')197```198199Как показано выше, функция [`getcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.getcontext) обращается к текущему контексту и позволяет изменять настройки. Такой подход удовлетворяет потребности большинства приложений.200201Для более сложной работы может быть полезно создавать альтернативные контексты с помощью конструктора [`Context()`](https://python-all.ru/3.14/library/decimal.html#decimal.Context). Чтобы сделать альтернативный контекст активным, используйте функцию [`setcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.setcontext).202203В соответствии со стандартом модуль `decimal` предоставляет два готовых к использованию стандартных контекста: [`BasicContext`](https://python-all.ru/3.14/library/decimal.html#decimal.BasicContext) и [`ExtendedContext`](https://python-all.ru/3.14/library/decimal.html#decimal.ExtendedContext). Первый особенно полезен для отладки, так как многие ловушки в нём включены:204205```pycon206>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)207>>> setcontext(myothercontext)208>>> Decimal(1) / Decimal(7)209Decimal('0.142857142857142857142857142857142857142857142857142857142857')210211>>> ExtendedContext212Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,213 capitals=1, clamp=0, flags=[], traps=[])214>>> setcontext(ExtendedContext)215>>> Decimal(1) / Decimal(7)216Decimal('0.142857143')217>>> Decimal(42) / Decimal(0)218Decimal('Infinity')219220>>> setcontext(BasicContext)221>>> Decimal(42) / Decimal(0)222Traceback (most recent call last):223 File "<pyshell#143>", line 1, in -toplevel-224 Decimal(42) / Decimal(0)225DivisionByZero: x / 0226```227228Контексты также имеют флаги сигналов для мониторинга исключительных ситуаций, возникающих во время вычислений. Флаги остаются установленными до явного сброса, поэтому лучше всего сбрасывать флаги перед каждой группой контролируемых вычислений с помощью метода [`clear_flags()`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.clear_flags).229230```python231>>> setcontext(ExtendedContext)232>>> getcontext().clear_flags()233>>> Decimal(355) / Decimal(113)234Decimal('3.14159292')235>>> getcontext()236Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,237 capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[])238```239240Запись *flags* показывает, что рациональное приближение к π было округлено (цифры, выходящие за пределы точности контекста, отброшены) и что результат неточен (некоторые из отброшенных цифр были ненулевыми).241242Отдельные ловушки устанавливаются с помощью словаря в атрибуте [`traps`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.traps) контекста:243244```pycon245>>> setcontext(ExtendedContext)246>>> Decimal(1) / Decimal(0)247Decimal('Infinity')248>>> getcontext().traps[DivisionByZero] = 1249>>> Decimal(1) / Decimal(0)250Traceback (most recent call last):251 File "<pyshell#112>", line 1, in -toplevel-252 Decimal(1) / Decimal(0)253DivisionByZero: x / 0254```255256Большинство программ настраивают текущий контекст только один раз, в начале программы. И во многих приложениях данные преобразуются в [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal) с помощью одного приведения типа внутри цикла. После установки контекста и создания десятичных чисел основная часть программы манипулирует данными так же, как и с другими числовыми типами Python.257258## Объекты Decimal259260#### `class decimal.Decimal(value='0', context=None)`261262Создаёт новый объект `Decimal` на основе *value*.263264*value* может быть целым числом, строкой, кортежем, [`float`](https://python-all.ru/3.14/library/functions.html#float) или другим объектом `Decimal`. Если *value* не указано, возвращается `Decimal('0')`. Если *value* является строкой, она должна соответствовать синтаксису десятичной числовой строки после удаления начальных и конечных пробельных символов, а также символов подчёркивания во всей строке:265266```python267sign ::= '+' | '-'268digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'269indicator ::= 'e' | 'E'270digits ::= digit [digit]...271decimal-part ::= digits '.' [digits] | ['.'] digits272exponent-part ::= indicator [sign] digits273infinity ::= 'Infinity' | 'Inf'274nan ::= 'NaN' [digits] | 'sNaN' [digits]275numeric-value ::= decimal-part [exponent-part] | infinity276numeric-string ::= [sign] numeric-value | [sign] nan277```278279Другие десятичные цифры Unicode также допускаются там, где `digit` встречается выше. К ним относятся десятичные цифры из различных других алфавитов (например, арабо-индийские цифры и деванагари) вместе с полноширинными цифрами от `'\uff10'` до `'\uff19'`. Регистр не учитывается, так что, например, `inf`, `Inf`, `INFINITY` и `iNfINity` являются допустимыми вариантами написания положительной бесконечности.280281Если *value* является [`tuple`](https://python-all.ru/3.14/library/stdtypes.html#tuple), он должен содержать три компонента: знак (`0` для положительного или `1` для отрицательного), `tuple` цифр и целочисленный показатель степени. Например, `Decimal((0, (1, 4, 1, 4), -3))` возвращает `Decimal('1.414')`.282283Если *value* является [`float`](https://python-all.ru/3.14/library/functions.html#float), двоичное значение с плавающей запятой без потерь преобразуется в его точный десятичный эквивалент. Это преобразование часто может потребовать 53 или более цифр точности. Например, `Decimal(float('1.1'))` преобразуется в `Decimal('1.100000000000000088817841970012523233890533447265625')`.284285Точность *context* не влияет на количество сохраняемых цифр. Оно определяется исключительно количеством цифр в *value*. Например, `Decimal('3.00000')` сохраняет все пять нулей, даже если точность контекста равна всего трём.286287Назначение аргумента *context* – определять, что делать, если *value* является некорректной строкой. Если контекст перехватывает [`InvalidOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.InvalidOperation), возбуждается исключение; в противном случае конструктор возвращает новый Decimal со значением `NaN`.288289После создания объекты `Decimal` неизменяемы.290291Изменено в версии 3.2: Теперь аргумент конструктора может быть [`float`](https://python-all.ru/3.14/library/functions.html#float) экземпляром.292293Изменено в версии 3.3: Аргументы [`float`](https://python-all.ru/3.14/library/functions.html#float) возбуждают исключение, если [`FloatOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.FloatOperation) ловушка установлена. По умолчанию ловушка выключена.294295Изменено в версии 3.6: Символы подчёркивания разрешены для группировки, как и в литералах целых чисел и чисел с плавающей запятой в коде.296297Объекты десятичных чисел с плавающей запятой имеют много общих свойств с другими встроенными числовыми типами, такими как [`float`](https://python-all.ru/3.14/library/functions.html#float) и [`int`](https://python-all.ru/3.14/library/functions.html#int). К ним применимы все обычные математические операции и специальные методы. Кроме того, десятичные объекты можно копировать, сериализовать (pickle), выводить на печать, использовать в качестве ключей словаря, элементов множества, сравнивать, сортировать и преобразовывать к другому типу (например, `float` или `int`).298299Существуют небольшие различия между арифметикой над объектами Decimal и арифметикой над целыми числами и числами с плавающей запятой. Когда оператор остатка `%` применяется к объектам Decimal, знак результата совпадает со знаком *dividend*, а не со знаком делителя:300301```python302>>> (-7) % 43031304>>> Decimal(-7) % Decimal(4)305Decimal('-3')306```307308Оператор целочисленного деления `//` ведёт себя аналогично: возвращает целую часть истинного частного (отсечение к нулю), а не его пол, чтобы сохранить обычное тождество `x == (x // y) * y + x % y`:309310```python311>>> -7 // 4312-2313>>> Decimal(-7) // Decimal(4)314Decimal('-1')315```316317Операторы `%` и `//` реализуют операции `remainder` и `divide-integer` (соответственно), как описано в спецификации.318319Объекты Decimal в общем случае нельзя комбинировать с числами с плавающей запятой или экземплярами [`fractions.Fraction`](https://python-all.ru/3.14/library/fractions.html#fractions.Fraction) в арифметических операциях: попытка добавить `Decimal` к [`float`](https://python-all.ru/3.14/library/functions.html#float), например, вызовет [`TypeError`](https://python-all.ru/3.14/library/exceptions.html#TypeError). Однако можно использовать операторы сравнения Python для сравнения экземпляра `Decimal` `x` с другим числом `y`. Это позволяет избежать путаницы при проверке равенства чисел разных типов.320321Изменено в версии 3.2: Сравнение между экземплярами `Decimal` и другими числовыми типами теперь полностью поддерживается.322323В дополнение к стандартным числовым свойствам объекты десятичных чисел с плавающей запятой также имеют ряд специализированных методов:324325#### `adjusted()`326327Возвращает скорректированный показатель степени после сдвига самых правых цифр коэффициента до тех пор, пока не останется только ведущая цифра: `Decimal('321e+5').adjusted()` возвращает семь. Используется для определения положения самой значащей цифры относительно десятичной точки.328329#### `as_integer_ratio()`330331Возвращает пару `(n, d)` целых чисел, представляющих данный экземпляр `Decimal` в виде дроби, в несократимом виде и с положительным знаменателем:332333```python334>>> Decimal('-3.14').as_integer_ratio()335(-157, 50)336```337338Преобразование точное. Возбуждает OverflowError для бесконечностей и ValueError для NaN.339340Добавлено в версии 3.6.341342#### `as_tuple()`343344Возвращает [именованный кортеж](https://python-all.ru/3.14/glossary.html#term-named-tuple) представление числа: `DecimalTuple(sign, digits, exponent)`.345346#### `canonical()`347348Возвращает каноническую кодировку аргумента. В настоящее время кодировка экземпляра `Decimal` всегда канонична, поэтому эта операция возвращает свой аргумент без изменений.349350#### `compare(other, context=None)`351352Сравнивает значения двух экземпляров Decimal. `compare()` возвращает экземпляр Decimal; если хотя бы один операнд является NaN, результат также будет NaN:353354```python355a or b is a NaN ==> Decimal('NaN')356a < b ==> Decimal('-1')357a == b ==> Decimal('0')358a > b ==> Decimal('1')359```360361#### `compare_signal(other, context=None)`362363Эта операция идентична методу [`compare()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.compare), за исключением того, что все NaN сигнализируют. То есть, если ни один операнд не является сигнальным NaN, то любой тихий NaN обрабатывается так, как если бы он был сигнальным NaN.364365#### `compare_total(other, context=None)`366367Сравнивает два операнда, используя их абстрактное представление, а не числовое значение. Аналогично методу [`compare()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.compare), но результат задаёт полный порядок на экземплярах `Decimal`. Два экземпляра `Decimal` с одинаковым числовым значением, но разными представлениями, в этом порядке считаются неравными:368369```python370>>> Decimal('12.0').compare_total(Decimal('12'))371Decimal('-1')372```373374Тихие и сигнальные NaN также включены в полный порядок. Результат этой функции равен `Decimal('0')`, если оба операнда имеют одинаковое представление, `Decimal('-1')`, если первый операнд меньше второго в полном порядке, и `Decimal('1')`, если первый операнд больше второго. См. спецификацию для подробностей полного порядка.375376Эта операция не зависит от контекста и является тихой: никакие флаги не меняются и округление не выполняется. Исключение составляет C-версия, которая может возбудить InvalidOperation, если второй операнд невозможно точно преобразовать.377378#### `compare_total_mag(other, context=None)`379380Сравнивает два операнда, используя их абстрактное представление, а не их значение, как в [`compare_total()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.compare_total), но игнорируя знак каждого операнда. `x.compare_total_mag(y)` эквивалентно `x.copy_abs().compare_total(y.copy_abs())`.381382Эта операция не зависит от контекста и является тихой: никакие флаги не меняются и округление не выполняется. Исключение составляет C-версия, которая может возбудить InvalidOperation, если второй операнд невозможно точно преобразовать.383384#### `conjugate()`385386Просто возвращает self; этот метод существует только для соответствия спецификации Decimal.387388#### `copy_abs()`389390Возвращает абсолютное значение аргумента. Эта операция не зависит от контекста и является тихой: флаги не изменяются и округление не выполняется.391392#### `copy_negate()`393394Возвращает отрицание аргумента. Эта операция не зависит от контекста и является тихой: флаги не изменяются и округление не выполняется.395396#### `copy_sign(other, context=None)`397398Возвращает копию первого операнда со знаком, установленным таким же, как знак второго операнда. Например:399400```python401>>> Decimal('2.3').copy_sign(Decimal('-1.5'))402Decimal('-2.3')403```404405Эта операция не зависит от контекста и является тихой: никакие флаги не меняются и округление не выполняется. Исключение составляет C-версия, которая может возбудить InvalidOperation, если второй операнд невозможно точно преобразовать.406407#### `exp(context=None)`408409Возвращает значение (натуральной) показательной функции `e**x` для заданного числа. Результат корректно округляется с использованием режима округления [`ROUND_HALF_EVEN`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_EVEN).410411```python412>>> Decimal(1).exp()413Decimal('2.718281828459045235360287471')414>>> Decimal(321).exp()415Decimal('2.561702493119680037517373933E+139')416```417418#### `classmethod from_float(f, /)`419420Альтернативный конструктор, принимающий только экземпляры [`float`](https://python-all.ru/3.14/library/functions.html#float) или [`int`](https://python-all.ru/3.14/library/functions.html#int).421422Обратите внимание: `Decimal.from_float(0.1)` не то же самое, что `Decimal('0.1')`. Поскольку 0.1 не может быть точно представлен в двоичной арифметике с плавающей запятой, значение сохраняется как ближайшее представимое значение, равное `0x1.999999999999ap-4`. Эквивалентное значение в десятичной записи – `0.1000000000000000055511151231257827021181583404541015625`.423424> **Примечание**425>426> Начиная с Python 3.2, экземпляр `Decimal` также можно создать напрямую из [`float`](https://python-all.ru/3.14/library/functions.html#float).427428```pycon429>>> Decimal.from_float(0.1)430Decimal('0.1000000000000000055511151231257827021181583404541015625')431>>> Decimal.from_float(float('nan'))432Decimal('NaN')433>>> Decimal.from_float(float('inf'))434Decimal('Infinity')435>>> Decimal.from_float(float('-inf'))436Decimal('-Infinity')437```438439Добавлено в версии 3.1.440441#### `classmethod from_number(number, /)`442443Альтернативный конструктор, принимающий только экземпляры [`float`](https://python-all.ru/3.14/library/functions.html#float), [`int`](https://python-all.ru/3.14/library/functions.html#int) или `Decimal`, но не строки или кортежи.444445```pycon446>>> Decimal.from_number(314)447Decimal('314')448>>> Decimal.from_number(0.1)449Decimal('0.1000000000000000055511151231257827021181583404541015625')450>>> Decimal.from_number(Decimal('3.14'))451Decimal('3.14')452```453454Добавлено в версии 3.14.455456#### `fma(other, third, context=None)`457458Совмещённое умножение-сложение. Возвращает self\*other+third без округления промежуточного произведения self\*other.459460```python461>>> Decimal(2).fma(3, 5)462Decimal('11')463```464465#### `is_canonical()`466467Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент канонический, и [`False`](https://python-all.ru/3.14/library/constants.html#False) в противном случае. В настоящее время экземпляр `Decimal` всегда является каноническим, поэтому данная операция всегда возвращает `True`.468469#### `is_finite()`470471Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент – конечное число, и [`False`](https://python-all.ru/3.14/library/constants.html#False), если аргумент – бесконечность или NaN.472473#### `is_infinite()`474475Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент – положительная или отрицательная бесконечность, и [`False`](https://python-all.ru/3.14/library/constants.html#False) в противном случае.476477#### `is_nan()`478479Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент – (тихий или сигнальный) NaN, и [`False`](https://python-all.ru/3.14/library/constants.html#False) в противном случае.480481#### `is_normal(context=None)`482483Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент – *нормальное* конечное число. Возвращает [`False`](https://python-all.ru/3.14/library/constants.html#False), если аргумент – ноль, субнормальное число, бесконечность или NaN.484485#### `is_qnan()`486487Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент – тихий NaN, и [`False`](https://python-all.ru/3.14/library/constants.html#False) в противном случае.488489#### `is_signed()`490491Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент имеет отрицательный знак, и [`False`](https://python-all.ru/3.14/library/constants.html#False) в противном случае. Обратите внимание, что нули и NaN могут иметь знак.492493#### `is_snan()`494495Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент – сигнальный NaN, и [`False`](https://python-all.ru/3.14/library/constants.html#False) в противном случае.496497#### `is_subnormal(context=None)`498499Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент субнормальный, и [`False`](https://python-all.ru/3.14/library/constants.html#False) в противном случае.500501#### `is_zero()`502503Возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True), если аргумент – (положительный или отрицательный) ноль, и [`False`](https://python-all.ru/3.14/library/constants.html#False) в противном случае.504505#### `ln(context=None)`506507Возвращает натуральный (по основанию e) логарифм операнда. Результат правильно округляется с использованием режима округления [`ROUND_HALF_EVEN`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_EVEN).508509#### `log10(context=None)`510511Возвращает десятичный логарифм операнда. Результат правильно округляется с использованием режима округления [`ROUND_HALF_EVEN`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_EVEN).512513#### `logb(context=None)`514515Для ненулевого числа возвращает скорректированный порядок операнда в виде экземпляра `Decimal`. Если операнд – ноль, то возвращается `Decimal('-Infinity')` и поднимается флаг [`DivisionByZero`](https://python-all.ru/3.14/library/decimal.html#decimal.DivisionByZero). Если операнд – бесконечность, то возвращается `Decimal('Infinity')`.516517#### `logical_and(other, context=None)`518519`logical_and()` – логическая операция, которая принимает два *логических операнда* (см. [Логические операнды](https://python-all.ru/3.14/library/decimal.html#logical-operands-label)). Результат – поразрядное `and` двух операндов.520521#### `logical_invert(context=None)`522523`logical_invert()` – логическая операция. Результат – поразрядная инверсия операнда.524525#### `logical_or(other, context=None)`526527`logical_or()` – логическая операция, которая принимает два *логических операнда* (см. [Логические операнды](https://python-all.ru/3.14/library/decimal.html#logical-operands-label)). Результат – поразрядное `or` двух операндов.528529#### `logical_xor(other, context=None)`530531`logical_xor()` – логическая операция, которая принимает два *логических операнда* (см. [Логические операнды](https://python-all.ru/3.14/library/decimal.html#logical-operands-label)). Результат – поразрядное исключающее ИЛИ двух операндов.532533#### `max(other, context=None)`534535Подобно `max(self, other)`, за исключением того, что перед возвратом применяется правило округления контекста и что значения `NaN` либо сигнализируются, либо игнорируются (в зависимости от контекста и того, являются ли они сигнализирующими или тихими).536537#### `max_mag(other, context=None)`538539Подобно методу [`max()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.max), но сравнение выполняется с использованием абсолютных значений операндов.540541#### `min(other, context=None)`542543Подобно `min(self, other)`, за исключением того, что перед возвратом применяется правило округления контекста и что значения `NaN` либо сигнализируются, либо игнорируются (в зависимости от контекста и того, являются ли они сигнализирующими или тихими).544545#### `min_mag(other, context=None)`546547Подобно методу [`min()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.min), но сравнение выполняется с использованием абсолютных значений операндов.548549#### `next_minus(context=None)`550551Возвращает наибольшее число, представимое в заданном контексте (или в контексте текущего потока, если контекст не задан), которое меньше заданного операнда.552553#### `next_plus(context=None)`554555Возвращает наименьшее число, представимое в заданном контексте (или в контексте текущего потока, если контекст не задан), которое больше заданного операнда.556557#### `next_toward(other, context=None)`558559Если два операнда не равны, возвращает число, ближайшее к первому операнду в направлении второго операнда. Если оба операнда численно равны, возвращает копию первого операнда со знаком, установленным таким же, как знак второго операнда.560561#### `normalize(context=None)`562563Используется для получения канонических значений класса эквивалентности в текущем контексте или в указанном контексте.564565Эта операция имеет ту же семантику, что и унарный плюс, за исключением того, что если конечный результат конечен, он приводится к своей простейшей форме: все конечные нули удаляются, а знак сохраняется. То есть, пока коэффициент не равен нулю и кратен десяти, коэффициент делится на десять, а показатель степени увеличивается на 1. В противном случае (коэффициент равен нулю) показатель степени устанавливается в 0. Во всех случаях знак не изменяется.566567Например, `Decimal('32.100')` и `Decimal('0.321000e+2')` оба нормализуются к эквивалентному значению `Decimal('32.1')`.568569Обратите внимание, что округление применяется *до* приведения к простейшей форме.570571В последних версиях спецификации эта операция также известна как `reduce`.572573#### `number_class(context=None)`574575Возвращает строку, описывающую *класс* операнда. Возвращаемое значение является одной из следующих десяти строк.576577- `"-Infinity"` – указывает, что операнд является отрицательной бесконечностью.578- `"-Normal"` – указывает, что операнд является отрицательным нормальным числом.579- `"-Subnormal"` – указывает, что операнд отрицательный и субнормальный.580- `"-Zero"` – указывает, что операнд является отрицательным нулём.581- `"+Zero"` – указывает, что операнд является положительным нулём.582- `"+Subnormal"` – указывает, что операнд положительный и субнормальный.583- `"+Normal"` – указывает, что операнд является положительным нормальным числом.584- `"+Infinity"` – указывает, что операнд является положительной бесконечностью.585- `"NaN"` – указывает, что операнд является тихим NaN (не числом).586- `"sNaN"` – указывает, что операнд является сигнализирующим NaN.587588#### `quantize(exp, rounding=None, context=None)`589590Возвращает значение, равное первому операнду после округления и имеющее экспоненту второго операнда.591592```python593>>> Decimal('1.41421356').quantize(Decimal('1.000'))594Decimal('1.414')595```596597В отличие от других операций, если длина коэффициента после операции quantize превышает точность, то сигнализируется [`InvalidOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.InvalidOperation). Это гарантирует, что, за исключением ошибочных ситуаций, экспонента после квантования всегда равна экспоненте правого операнда.598599Также, в отличие от других операций, quantize никогда не сигнализирует Underflow, даже если результат субнормален и неточен.600601Если экспонента второго операнда больше, чем первого, может потребоваться округление. В этом случае режим округления определяется аргументом `rounding`, если он передан, иначе аргументом `context`; если ни один из аргументов не передан, используется режим округления контекста текущего потока.602603Ошибка возвращается, если результирующая экспонента больше [`Emax`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Emax) или меньше [`Etiny()`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Etiny).604605#### `radix()`606607Возвращает `Decimal(10)` – основание системы счисления (базу), в которой класс `Decimal` выполняет все арифметические операции. Включено для совместимости со спецификацией.608609#### `remainder_near(other, context=None)`610611Возвращает остаток от деления *self* на *other*. Отличается от `self % other` тем, что знак остатка выбирается так, чтобы минимизировать его абсолютное значение. Точнее, возвращаемое значение равно `self - n * other`, где `n` – целое число, ближайшее к точному значению `self / other`, а если два целых числа одинаково близки, выбирается чётное.612613Если результат равен нулю, его знак будет знаком *self*.614615```python616>>> Decimal(18).remainder_near(Decimal(10))617Decimal('-2')618>>> Decimal(25).remainder_near(Decimal(10))619Decimal('5')620>>> Decimal(35).remainder_near(Decimal(10))621Decimal('-5')622```623624#### `rotate(other, context=None)`625626Возвращает результат вращения цифр первого операнда на величину, заданную вторым операндом. Второй операнд должен быть целым числом в диапазоне от -precision до precision. Абсолютное значение второго операнда задаёт количество позиций для вращения. Если второй операнд положителен, вращение выполняется влево; в противном случае вращение выполняется вправо. Коэффициент первого операнда при необходимости дополняется слева нулями до длины precision. Знак и экспонента первого операнда не изменяются.627628#### `same_quantum(other, context=None)`629630Проверяет, имеют ли self и other одинаковую экспоненту или оба равны `NaN`.631632Эта операция не зависит от контекста и является тихой: никакие флаги не меняются и округление не выполняется. Исключение составляет C-версия, которая может возбудить InvalidOperation, если второй операнд невозможно точно преобразовать.633634#### `scaleb(other, context=None)`635636Возвращает первый операнд с экспонентой, скорректированной на второй операнд. Эквивалентно умножению первого операнда на `10**other`. Второй операнд должен быть целым числом.637638#### `shift(other, context=None)`639640Возвращает результат сдвига цифр первого операнда на величину, заданную вторым операндом. Второй операнд должен быть целым числом в диапазоне от -precision до precision. Абсолютное значение второго операнда задаёт количество позиций для сдвига. Если второй операнд положителен, сдвиг выполняется влево; в противном случае сдвиг выполняется вправо. Вдвигаемые в коэффициент цифры являются нулями. Знак и экспонента первого операнда не изменяются.641642#### `sqrt(context=None)`643644Возвращает квадратный корень аргумента с полной точностью.645646#### `to_eng_string(context=None)`647648Преобразует в строку, используя инженерную запись, если нужен показатель степени.649650В инженерной записи показатель степени кратен трём. Из-за этого слева от десятичной запятой может оставаться до трёх цифр, и может потребоваться добавление одного или двух конечных нулей.651652Например, это преобразует `Decimal('123E+1')` в `Decimal('1.23E+3')`.653654#### `to_integral(rounding=None, context=None)`655656Идентичен методу [`to_integral_value()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.to_integral_value). Имя `to_integral` сохранено для совместимости со старыми версиями.657658#### `to_integral_exact(rounding=None, context=None)`659660Округляет до ближайшего целого, сигнализируя [`Inexact`](https://python-all.ru/3.14/library/decimal.html#decimal.Inexact) или [`Rounded`](https://python-all.ru/3.14/library/decimal.html#decimal.Rounded) в зависимости от ситуации, если округление происходит. Режим округления определяется параметром `rounding`, если он передан, иначе переданным `context`. Если ни один из параметров не передан, используется режим округления текущего контекста.661662#### `to_integral_value(rounding=None, context=None)`663664Округляет до ближайшего целого без сигнализации [`Inexact`](https://python-all.ru/3.14/library/decimal.html#decimal.Inexact) или [`Rounded`](https://python-all.ru/3.14/library/decimal.html#decimal.Rounded). Если передан, применяет *rounding*; в противном случае использует метод округления из предоставленного *context* или текущего контекста.665666Десятичные числа можно округлять с помощью функции [`round()`](https://python-all.ru/3.14/library/functions.html#round):667668#### `round(number)`669670#### `round(number, ndigits)`671672Если *ndigits* не указан или равен `None`, возвращает ближайшее [`int`](https://python-all.ru/3.14/library/functions.html#int) к *number*, при округлении связей (ties) до четного, игнорируя режим округления контекста `Decimal`. Вызывает [`OverflowError`](https://python-all.ru/3.14/library/exceptions.html#OverflowError), если *number* – бесконечность, или [`ValueError`](https://python-all.ru/3.14/library/exceptions.html#ValueError), если это (тихий или сигнальный) NaN.673674Если *ndigits* является [`int`](https://python-all.ru/3.14/library/functions.html#int), учитывается режим округления контекста, и возвращается `Decimal`, представляющий *number*, округлённый до ближайшего кратного `Decimal('1E-ndigits')`; в этом случае `round(number, ndigits)` эквивалентно `self.quantize(Decimal('1E-ndigits'))`. Возвращает `Decimal('NaN')`, если *number* является тихим NaN. Вызывает [`InvalidOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.InvalidOperation), если *number* является бесконечностью, сигнальным NaN, или если длина коэффициента после операции quantize превышает точность текущего контекста. Иными словами, для неграничных случаев:675676- если *ndigits* положителен, возвращает *number*, округлённый до *ndigits* десятичных знаков;677- если *ndigits* равен нулю, возвращает *number*, округлённый до ближайшего целого;678- если *ndigits* отрицателен, возвращает *number*, округлённый до ближайшего кратного `10**abs(ndigits)`.679680Например:681682```python683>>> from decimal import Decimal, getcontext, ROUND_DOWN684>>> getcontext().rounding = ROUND_DOWN685>>> round(Decimal('3.75')) # Округление контекста игнорируется6864687>>> round(Decimal('3.5')) # округление до ближайшего чётного6884689>>> round(Decimal('3.75'), 0) # использует округление контекста690Decimal('3')691>>> round(Decimal('3.75'), 1)692Decimal('3.7')693>>> round(Decimal('3.75'), -1)694Decimal('0E+1')695```696697### Логические операнды698699Методы [`logical_and()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.logical_and), [`logical_invert()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.logical_invert), [`logical_or()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.logical_or) и [`logical_xor()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.logical_xor) ожидают, что их аргументы будут *логическими операндами*. *Логический операнд* – это экземпляр [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal), у которого экспонента и знак равны нулю, а все цифры равны либо `0`, либо `1`.700701## Объекты контекста702703Контексты – это среды для арифметических операций. Они управляют точностью, задают правила округления, определяют, какие сигналы обрабатываются как исключения, и ограничивают диапазон для экспонент.704705Каждый поток имеет собственный текущий контекст, доступ к которому или изменение которого осуществляется с помощью функций [`getcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.getcontext) и [`setcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.setcontext):706707#### `decimal.getcontext()`708709Возвращает текущий контекст активного потока.710711#### `decimal.setcontext(c, /)`712713Устанавливает текущий контекст активного потока в *c*.714715Также можно использовать оператор [`with`](https://python-all.ru/3.14/reference/compound_stmts.html#with) и функцию [`localcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.localcontext) для временного изменения активного контекста.716717#### `decimal.localcontext(ctx=None, **kwargs)`718719Возвращает менеджер контекста, который устанавливает текущий контекст активного потока в копию *ctx* при входе в оператор with и восстанавливает предыдущий контекст при выходе из оператора with. Если контекст не указан, используется копия текущего контекста. Аргумент *kwargs* используется для установки атрибутов нового контекста.720721Например, следующий код устанавливает текущую точность десятичных чисел в 42 знака, выполняет вычисление и затем автоматически восстанавливает предыдущий контекст:722723```python724from decimal import localcontext725726with localcontext() as ctx:727 ctx.prec = 42 # Выполнить вычисление с высокой точностью728 s = calculate_something()729s = +s # Округлить конечный результат до стандартной точности730```731732С использованием именованных аргументов код будет следующим:733734```python735from decimal import localcontext736737with localcontext(prec=42) as ctx:738 s = calculate_something()739s = +s740```741742Вызывает [`TypeError`](https://python-all.ru/3.14/library/exceptions.html#TypeError), если *kwargs* содержит атрибут, который не поддерживается [`Context`](https://python-all.ru/3.14/library/decimal.html#decimal.Context). Вызывает либо `TypeError`, либо [`ValueError`](https://python-all.ru/3.14/library/exceptions.html#ValueError), если *kwargs* содержит недопустимое значение для атрибута.743744Изменено в версии 3.11: `localcontext()` теперь поддерживает установку атрибутов контекста с помощью именованных аргументов.745746#### `decimal.IEEEContext(bits)`747748Возвращает объект контекста, инициализированный с соответствующими значениями для одного из форматов обмена IEEE. Аргумент должен быть кратен 32 и меньше [`IEEE_CONTEXT_MAX_BITS`](https://python-all.ru/3.14/library/decimal.html#decimal.IEEE_CONTEXT_MAX_BITS).749750Добавлено в версии 3.14.751752Новые контексты также можно создать с помощью конструктора [`Context`](https://python-all.ru/3.14/library/decimal.html#decimal.Context), описанного ниже. Кроме того, модуль предоставляет три готовых контекста:753754#### `decimal.BasicContext`755756Это стандартный контекст, определённый спецификацией General Decimal Arithmetic Specification. Точность установлена в девять. Округление установлено в [`ROUND_HALF_UP`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_UP). Все флаги сброшены. Все ловушки включены (обрабатываются как исключения), кроме [`Inexact`](https://python-all.ru/3.14/library/decimal.html#decimal.Inexact), [`Rounded`](https://python-all.ru/3.14/library/decimal.html#decimal.Rounded) и [`Subnormal`](https://python-all.ru/3.14/library/decimal.html#decimal.Subnormal).757758Поскольку многие ловушки включены, этот контекст полезен для отладки.759760#### `decimal.ExtendedContext`761762Это стандартный контекст, определённый спецификацией General Decimal Arithmetic Specification. Точность установлена в девять. Округление установлено в [`ROUND_HALF_EVEN`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_EVEN). Все флаги сброшены. Никакие ловушки не включены (поэтому исключения не возникают во время вычислений).763764Поскольку ловушки отключены, этот контекст полезен для приложений, которые предпочитают получать в результате значения `NaN` или `Infinity` вместо возбуждения исключений. Это позволяет приложению завершить выполнение при наличии условий, которые в противном случае остановили бы программу.765766#### `decimal.DefaultContext`767768Этот контекст используется конструктором [`Context`](https://python-all.ru/3.14/library/decimal.html#decimal.Context) в качестве прототипа для новых контекстов. Изменение поля (например, точности) приводит к изменению значения по умолчанию для новых контекстов, создаваемых конструктором `Context`.769770Этот контекст наиболее полезен в многопоточных средах. Изменение одного из полей до запуска потоков приводит к установке общесистемных значений по умолчанию. Изменять поля после запуска потоков не рекомендуется, так как это потребовало бы синхронизации потоков для предотвращения состояний гонки.771772В однопоточных средах лучше вообще не использовать этот контекст. Вместо этого просто создавайте контексты явно, как описано ниже.773774Значения по умолчанию: [`Context.prec`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.prec)=`28`, [`Context.rounding`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.rounding)=[`ROUND_HALF_EVEN`](https://python-all.ru/3.14/library/decimal.html#decimal.ROUND_HALF_EVEN) и включенные ловушки для [`Overflow`](https://python-all.ru/3.14/library/decimal.html#decimal.Overflow), [`InvalidOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.InvalidOperation) и [`DivisionByZero`](https://python-all.ru/3.14/library/decimal.html#decimal.DivisionByZero).775776В дополнение к трём встроенным контекстам новые контексты можно создать с помощью конструктора [`Context`](https://python-all.ru/3.14/library/decimal.html#decimal.Context).777778#### `class decimal.Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)`779780Создаёт новый контекст. Если поле не указано или равно [`None`](https://python-all.ru/3.14/library/constants.html#None), значения по умолчанию копируются из [`DefaultContext`](https://python-all.ru/3.14/library/decimal.html#decimal.DefaultContext). Если поле *flags* не указано или равно `None`, все флаги сбрасываются.781782#### `prec`783784Целое число в диапазоне \[`1`, [`MAX_PREC`](https://python-all.ru/3.14/library/decimal.html#decimal.MAX_PREC)\], задающее точность арифметических операций в контексте.785786#### `rounding`787788Одна из констант, перечисленных в разделе [Режимы округления](https://python-all.ru/3.14/library/decimal.html#rounding-modes).789790#### `traps`791792#### `flags`793794Списки устанавливаемых сигналов. Обычно в новых контекстах следует только устанавливать ловушки, а флаги оставлять сброшенными.795796#### `Emin`797798#### `Emax`799800Integers specifying the outer limits allowable for exponents. *Emin* must be in the range \[[`MIN_EMIN`](https://python-all.ru/3.14/library/decimal.html#decimal.MIN_EMIN), `0`\], *Emax* in the range \[`0`, [`MAX_EMAX`](https://python-all.ru/3.14/library/decimal.html#decimal.MAX_EMAX)\].801802#### `capitals`803804Либо `0`, либо `1` (по умолчанию). Если установлено `1`, экспоненты выводятся с заглавной `E`; в противном случае используется строчная `e`: `Decimal('6.02e+23')`.805806#### `clamp`807808Либо `0` (по умолчанию), либо `1`. Если установлено `1`, экспонента `e` экземпляра [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal), представимого в этом контексте, строго ограничена диапазоном `Emin - prec + 1 <= e <= Emax - prec + 1`. Если *clamp* равно `0`, то действует более слабое условие: скорректированная экспонента экземпляра `Decimal` не превышает [`Emax`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Emax). Когда *clamp* равно `1`, большое нормальное число, если возможно, уменьшает свою экспоненту и добавляет соответствующее количество нулей к коэффициенту, чтобы соответствовать ограничениям на экспоненту; это сохраняет значение числа, но теряет информацию о значимых конечных нулях. Например:809810```python811>>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999')812Decimal('1.23000E+999')813```814815Значение *clamp*, равное `1`, обеспечивает совместимость с форматами обмена десятичными числами фиксированной ширины, определёнными в IEEE 754.816817Класс `Context` определяет несколько методов общего назначения, а также большое количество методов для выполнения арифметических операций непосредственно в заданном контексте. Кроме того, для каждого из методов [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal), описанных выше (за исключением методов [`adjusted()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.adjusted) и [`as_tuple()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.as_tuple)), существует соответствующий метод `Context`. Например, для экземпляра `Context` `C` и экземпляра `Decimal` `x`, `C.exp(x)` эквивалентно `x.exp(context=C)`. Каждый метод `Context` принимает целое число Python (экземпляр [`int`](https://python-all.ru/3.14/library/functions.html#int)) везде, где принимается экземпляр Decimal.818819#### `clear_flags()`820821Сбрасывает все флаги в `0`.822823#### `clear_traps()`824825Сбрасывает все ловушки в `0`.826827Добавлено в версии 3.3.828829#### `copy()`830831Возвращает копию контекста.832833#### `copy_decimal(num, /)`834835Возвращает копию экземпляра Decimal num.836837#### `create_decimal(num='0', /)`838839Создаёт новый экземпляр Decimal из *num*, но используя *self* в качестве контекста. В отличие от конструктора [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal), к преобразованию применяются точность контекста, метод округления, флаги и ловушки.840841Это полезно, поскольку константы часто задаются с большей точностью, чем требуется приложению. Ещё одно преимущество в том, что округление немедленно устраняет нежелательные эффекты от цифр за пределами текущей точности. В следующем примере использование неокруглённых входных данных означает, что добавление нуля к сумме может изменить результат:842843```pycon844>>> getcontext().prec = 3845>>> Decimal('3.4445') + Decimal('1.0023')846Decimal('4.45')847>>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023')848Decimal('4.44')849```850851Этот метод реализует операцию преобразования в число из спецификации IBM. Если аргумент – строка, начальные и конечные пробелы или знаки подчёркивания не допускаются.852853#### `create_decimal_from_float(f, /)`854855Создаёт новый экземпляр Decimal из числа с плавающей точкой *f*, округляя с использованием *self* в качестве контекста. В отличие от метода класса [`Decimal.from_float()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.from_float), к преобразованию применяются точность контекста, метод округления, флаги и ловушки.856857```pycon858>>> context = Context(prec=5, rounding=ROUND_DOWN)859>>> context.create_decimal_from_float(math.pi)860Decimal('3.1415')861>>> context = Context(prec=5, traps=[Inexact])862>>> context.create_decimal_from_float(math.pi)863Traceback (most recent call last):864 ...865decimal.Inexact: None866```867868Добавлено в версии 3.1.869870#### `Etiny()`871872Возвращает значение, равное `Emin - prec + 1`, которое является минимальным значением экспоненты для субнормальных результатов. При антипереполнении (underflow) экспонента устанавливается в [`Etiny`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Etiny).873874#### `Etop()`875876Возвращает значение, равное `Emax - prec + 1`.877878Обычный подход к работе с десятичными числами заключается в создании экземпляров [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal) и последующем применении арифметических операций, которые выполняются в текущем контексте активного потока. Альтернативный подход – использовать методы контекста для вычислений в заданном контексте. Эти методы аналогичны методам класса `Decimal` и здесь лишь кратко перечислены.879880#### `abs(x, /)`881882Возвращает абсолютное значение *x*.883884#### `add(x, y, /)`885886Возвращает сумму *x* и *y*.887888#### `canonical(x, /)`889890Возвращает тот же объект Decimal *x*.891892#### `compare(x, y, /)`893894Сравнивает *x* и *y* численно.895896#### `compare_signal(x, y, /)`897898Сравнивает значения двух операндов численно.899900#### `compare_total(x, y, /)`901902Сравнивает два операнда по их абстрактному представлению.903904#### `compare_total_mag(x, y, /)`905906Сравнивает два операнда по их абстрактному представлению, игнорируя знак.907908#### `copy_abs(x, /)`909910Возвращает копию *x* с установленным в 0 знаком.911912#### `copy_negate(x, /)`913914Возвращает копию *x* с инвертированным знаком.915916#### `copy_sign(x, y, /)`917918Копирует знак из *y* в *x*.919920#### `divide(x, y, /)`921922Возвращает *x*, делённое на *y*.923924#### `divide_int(x, y, /)`925926Возвращает *x*, делённое на *y*, с усечением до целого.927928#### `divmod(x, y, /)`929930Делит два числа и возвращает целую часть результата.931932#### `exp(x, /)`933934Возвращает `e ** x`.935936#### `fma(x, y, z, /)`937938Возвращает *x*, умноженное на *y*, плюс *z*.939940#### `is_canonical(x, /)`941942Возвращает `True`, если *x* является каноническим; в противном случае возвращает `False`.943944#### `is_finite(x, /)`945946Возвращает `True`, если *x* является конечным; в противном случае возвращает `False`.947948#### `is_infinite(x, /)`949950Возвращает `True`, если *x* является бесконечным; в противном случае возвращает `False`.951952#### `is_nan(x, /)`953954Возвращает `True`, если *x* является qNaN или sNaN; в противном случае возвращает `False`.955956#### `is_normal(x, /)`957958Возвращает `True`, если *x* является нормальным числом; в противном случае возвращает `False`.959960#### `is_qnan(x, /)`961962Возвращает `True`, если *x* является тихим NaN; в противном случае возвращает `False`.963964#### `is_signed(x, /)`965966Возвращает `True`, если *x* является отрицательным; в противном случае возвращает `False`.967968#### `is_snan(x, /)`969970Возвращает `True`, если *x* является сигнальным NaN; в противном случае возвращает `False`.971972#### `is_subnormal(x, /)`973974Возвращает `True`, если *x* является субнормальным; в противном случае возвращает `False`.975976#### `is_zero(x, /)`977978Возвращает `True`, если *x* является нулём; в противном случае возвращает `False`.979980#### `ln(x, /)`981982Возвращает натуральный (по основанию e) логарифм *x*.983984#### `log10(x, /)`985986Возвращает десятичный логарифм *x*.987988#### `logb(x, /)`989990Возвращает показатель степени величины старшего разряда операнда.991992#### `logical_and(x, y, /)`993994Применяет логическую операцию *and* к соответствующим цифрам операндов.995996#### `logical_invert(x, /)`997998Инвертирует все цифры в *x*.9991000#### `logical_or(x, y, /)`10011002Применяет логическую операцию *or* к соответствующим цифрам операндов.10031004#### `logical_xor(x, y, /)`10051006Применяет логическую операцию *xor* к соответствующим цифрам операндов.10071008#### `max(x, y, /)`10091010Сравнивает два числа и возвращает наибольшее.10111012#### `max_mag(x, y, /)`10131014Сравнивает числа по модулю (игнорируя знак).10151016#### `min(x, y, /)`10171018Сравнивает два числа и возвращает наименьшее.10191020#### `min_mag(x, y, /)`10211022Сравнивает числа по модулю (игнорируя знак).10231024#### `minus(x, /)`10251026Минус соответствует унарному префиксному оператору минус в Python.10271028#### `multiply(x, y, /)`10291030Возвращает произведение *x* и *y*.10311032#### `next_minus(x, /)`10331034Возвращает наибольшее представимое число, меньшее чем *x*.10351036#### `next_plus(x, /)`10371038Возвращает наименьшее представимое число, большее чем *x*.10391040#### `next_toward(x, y, /)`10411042Возвращает число, ближайшее к *x* в направлении к *y*.10431044#### `normalize(x, /)`10451046Приводит *x* к простейшей форме.10471048#### `number_class(x, /)`10491050Возвращает указание на класс *x*.10511052#### `plus(x, /)`10531054Plus соответствует унарному префиксному оператору плюс в Python. Эта операция применяет точность и округление контекста, поэтому она *не* является тождественной операцией.10551056#### `power(x, y, modulo=None)`10571058Возвращает `x` в степени `y`, приведённое по модулю `modulo`, если он задан.10591060С двумя аргументами вычисляет `x**y`. Если `x` отрицательно, то `y` должно быть целым. Результат будет неточным, если только `y` не является целым и результат не конечен и не может быть точно выражен в ‘precision’ цифрах. Используется режим округления контекста. В версии Python результаты всегда правильно округляются.10611062`Decimal(0) ** Decimal(0)` приводит к `InvalidOperation`, и если `InvalidOperation` не перехвачено, то результатом будет `Decimal('NaN')`.10631064Изменено в версии 3.3: Модуль на C вычисляет `power()` через правильно округлённые функции [`exp()`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.exp) и [`ln()`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.ln). Результат хорошо определён, но лишь «почти всегда правильно округлён».10651066С тремя аргументами вычисляет `(x**y) % modulo`. Для формы с тремя аргументами действуют следующие ограничения на аргументы:10671068- все три аргумента должны быть целыми1069- `y` должно быть неотрицательным1070- по крайней мере один из `x` или `y` должен быть ненулевым1071- `modulo` должно быть ненулевым и содержать не более ‘precision’ цифр10721073Значение, получаемое из `Context.power(x, y, modulo)`, равно значению, которое было бы получено при вычислении `(x**y) % modulo` с неограниченной точностью, но вычисляется более эффективно. Показатель степени результата равен нулю, независимо от показателей степени `x`, `y` и `modulo`. Результат всегда точен.10741075#### `quantize(x, y, /)`10761077Возвращает значение, равное *x* (с округлением), с экспонентой *y*.10781079#### `radix()`10801081Просто возвращает 10, так как это Decimal, :)10821083#### `remainder(x, y, /)`10841085Возвращает остаток от целочисленного деления.10861087Знак результата, если он не равен нулю, совпадает со знаком исходного делимого.10881089#### `remainder_near(x, y, /)`10901091Возвращает `x - y * n`, где *n* – целое число, ближайшее к точному значению `x / y` (если результат равен 0, то его знак будет знаком *x*).10921093#### `rotate(x, y, /)`10941095Возвращает циклически сдвинутую копию *x* на *y* раз.10961097#### `same_quantum(x, y, /)`10981099Возвращает `True`, если два операнда имеют одинаковую экспоненту.11001101#### `scaleb(x, y, /)`11021103Возвращает первый операнд после добавления второго значения к его экспоненте.11041105#### `shift(x, y, /)`11061107Возвращает сдвинутую копию *x* на *y* раз.11081109#### `sqrt(x, /)`11101111Квадратный корень неотрицательного числа с точностью контекста.11121113#### `subtract(x, y, /)`11141115Возвращает разность *x* и *y*.11161117#### `to_eng_string(x, /)`11181119Преобразует в строку, используя инженерную запись, если нужен показатель степени.11201121В инженерной записи показатель степени кратен трём. Из-за этого слева от десятичной запятой может оставаться до трёх цифр, и может потребоваться добавление одного или двух конечных нулей.11221123#### `to_integral_exact(x, /)`11241125Округляет до целого.11261127#### `to_sci_string(x, /)`11281129Преобразует число в строку, используя научную запись.11301131## Константы11321133Константы в этом разделе имеют значение только для модуля C. Они также включены в чистую версию Python для совместимости.11341135| | 32-битный | 64-битный |1136| --- | --- | --- |1137| decimal.MAX\_PREC | `425000000` | `999999999999999999` |1138| decimal.MAX\_EMAX | `425000000` | `999999999999999999` |1139| decimal.MIN\_EMIN | `-425000000` | `-999999999999999999` |1140| decimal.MIN\_ETINY | `-849999999` | `-1999999999999999997` |1141| decimal.IEEE\_CONTEXT\_MAX\_BITS | `256` | `512` |11421143#### `decimal.HAVE_THREADS`11441145Значение равно `True`. Устарело, поскольку в Python теперь всегда есть потоки.11461147Устарело с версии 3.9.11481149#### `decimal.HAVE_CONTEXTVAR`11501151Значение по умолчанию – `True`. Если Python [`configured using the --without-decimal-contextvar option`](https://python-all.ru/3.14/using/configure.html#cmdoption-without-decimal-contextvar), версия на C использует локальный для потока контекст, а не локальный для корутины, и значение равно `False`. В некоторых сценариях с вложенными контекстами это несколько быстрее.11521153Добавлено в версии 3.8.3.11541155## Режимы округления11561157#### `decimal.ROUND_CEILING`11581159Округление в сторону `Infinity`.11601161#### `decimal.ROUND_DOWN`11621163Округление к нулю.11641165#### `decimal.ROUND_FLOOR`11661167Округление в сторону `-Infinity`.11681169#### `decimal.ROUND_HALF_DOWN`11701171Округление до ближайшего, при связях – к нулю.11721173#### `decimal.ROUND_HALF_EVEN`11741175Округление до ближайшего, при связях – до ближайшего чётного целого.11761177#### `decimal.ROUND_HALF_UP`11781179Округление до ближайшего, при связях – от нуля.11801181#### `decimal.ROUND_UP`11821183Округление от нуля.11841185#### `decimal.ROUND_05UP`11861187Округление от нуля, если последняя цифра после округления к нулю была бы 0 или 5; в противном случае округление к нулю.11881189## Сигналы11901191Сигналы представляют условия, возникающие во время вычислений. Каждый соответствует одному флагу контекста и одному включателю ловушки контекста.11921193Флаг контекста устанавливается при возникновении условия. После вычисления флаги могут быть проверены в информационных целях (например, чтобы определить, было ли вычисление точным). После проверки флагов необходимо очистить все флаги перед началом следующего вычисления.11941195Если для сигнала установлен включатель ловушки контекста, то условие вызывает возбуждение исключения Python. Например, если установлена ловушка [`DivisionByZero`](https://python-all.ru/3.14/library/decimal.html#decimal.DivisionByZero), то при возникновении условия возбуждается исключение [`DivisionByZero`](https://python-all.ru/3.14/library/decimal.html#decimal.DivisionByZero).11961197#### `class decimal.Clamped`11981199Изменён показатель степени для соответствия ограничениям представления.12001201Обычно усечение происходит, когда показатель степени выходит за пределы ограничений контекста [`Emin`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Emin) и [`Emax`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Emax). Если возможно, показатель степени уменьшается для соответствия путём добавления нулей к коэффициенту.12021203#### `class decimal.DecimalException`12041205Базовый класс для других сигналов и подкласс [`ArithmeticError`](https://python-all.ru/3.14/library/exceptions.html#ArithmeticError).12061207#### `class decimal.DivisionByZero`12081209Сигнализирует о делении небесконечного числа на ноль.12101211Может возникнуть при делении, делении по модулю или при возведении числа в отрицательную степень. Если этот сигнал не перехвачен, возвращает `Infinity` или `-Infinity` со знаком, определяемым входными данными вычисления.12121213#### `class decimal.Inexact`12141215Указывает, что произошло округление и результат не является точным.12161217Сигнализирует, когда при округлении были отброшены ненулевые цифры. Возвращается округлённый результат. Флаг сигнала или ловушка используется для обнаружения неточных результатов.12181219#### `class decimal.InvalidOperation`12201221Выполнена недопустимая операция.12221223Указывает, что была запрошена операция, не имеющая смысла. Если не перехвачена, возвращает `NaN`. Возможные причины включают:12241225```python1226Infinity - Infinity12270 * Infinity1228Infinity / Infinity1229x % 01230Infinity % x1231sqrt(-x) and x > 012320 ** 01233x ** (non-integer)1234x ** Infinity1235```12361237#### `class decimal.Overflow`12381239Числовое переполнение.12401241Указывает, что показатель степени больше [`Context.Emax`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Emax) после округления. Если не перехвачена, результат зависит от режима округления: либо округление внутрь до наибольшего представимого конечного числа, либо округление наружу до `Infinity`. В любом случае также сигнализируются [`Inexact`](https://python-all.ru/3.14/library/decimal.html#decimal.Inexact) и [`Rounded`](https://python-all.ru/3.14/library/decimal.html#decimal.Rounded).12421243#### `class decimal.Rounded`12441245Произошло округление, хотя, возможно, информация не была потеряна.12461247Срабатывает при каждом округлении, отбрасывающем цифры, даже если эти цифры нулевые (например, при округлении `5.00` до `5.0`). Если не перехвачено, возвращает результат без изменений. Этот сигнал используется для обнаружения потери значащих цифр.12481249#### `class decimal.Subnormal`12501251Экспонента была меньше [`Emin`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Emin) перед округлением.12521253Возникает, когда результат операции является субнормальным (экспонента слишком мала). Если не перехвачено, возвращает результат без изменений.12541255#### `class decimal.Underflow`12561257Числовое исчерпание с округлением результата до нуля.12581259Возникает, когда субнормальный результат округляется до нуля. Также срабатывают сигналы [`Inexact`](https://python-all.ru/3.14/library/decimal.html#decimal.Inexact) и [`Subnormal`](https://python-all.ru/3.14/library/decimal.html#decimal.Subnormal).12601261#### `class decimal.FloatOperation`12621263Включает более строгую семантику смешивания чисел с плавающей запятой и десятичных чисел.12641265Если сигнал не перехвачен (по умолчанию), смешивание чисел с плавающей запятой и десятичных чисел разрешено в конструкторе [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal), [`create_decimal()`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.create_decimal) и во всех операторах сравнения. Как преобразование, так и сравнение являются точными. Любое смешанное действие молча регистрируется установкой `FloatOperation` в флагах контекста. Явные преобразования с помощью [`from_float()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.from_float) или [`create_decimal_from_float()`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.create_decimal_from_float) не устанавливают флаг.12661267В противном случае (сигнал перехвачен), молчаливыми остаются только сравнения на равенство и явные преобразования. Все остальные смешанные операции возбуждают `FloatOperation`.12681269В следующей таблице приведена иерархия сигналов:12701271```python1272exceptions.ArithmeticError(exceptions.Exception)1273 DecimalException1274 Clamped1275 DivisionByZero(DecimalException, exceptions.ZeroDivisionError)1276 Inexact1277 Overflow(Inexact, Rounded)1278 Underflow(Inexact, Rounded, Subnormal)1279 InvalidOperation1280 Rounded1281 Subnormal1282 FloatOperation(DecimalException, exceptions.TypeError)1283```12841285## Примечания по числам с плавающей запятой12861287### Снижение ошибки округления за счёт увеличения точности12881289Использование десятичной арифметики с плавающей запятой устраняет ошибку десятичного представления (позволяя точно представить `0.1`); однако некоторые операции всё ещё могут приводить к ошибке округления, когда ненулевые цифры превышают фиксированную точность.12901291Эффекты ошибки округления могут усиливаться при сложении или вычитании почти компенсирующих друг друга величин, что приводит к потере значимости. Кнут приводит два поучительных примера, где округлённая арифметика с плавающей запятой с недостаточной точностью вызывает нарушение ассоциативного и дистрибутивного свойств сложения:12921293```pycon1294# Examples from Seminumerical Algorithms, Section 4.2.2.1295>>> from decimal import Decimal, getcontext1296>>> getcontext().prec = 812971298>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')1299>>> (u + v) + w1300Decimal('9.5111111')1301>>> u + (v + w)1302Decimal('10')13031304>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')1305>>> (u*v) + (u*w)1306Decimal('0.01')1307>>> u * (v+w)1308Decimal('0.0060000')1309```13101311Модуль `decimal` позволяет восстановить эти свойства за счёт достаточного увеличения точности, чтобы избежать потери значимости:13121313```pycon1314>>> getcontext().prec = 201315>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')1316>>> (u + v) + w1317Decimal('9.51111111')1318>>> u + (v + w)1319Decimal('9.51111111')1320>>>1321>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')1322>>> (u*v) + (u*w)1323Decimal('0.0060000')1324>>> u * (v+w)1325Decimal('0.0060000')1326```13271328### Особые значения13291330Система чисел модуля `decimal` предоставляет особые значения, включая `NaN`, `sNaN`, `-Infinity`, `Infinity`, а также два нуля: `+0` и `-0`.13311332Бесконечности можно создать напрямую с помощью `Decimal('Infinity')`. Также, они могут возникать при делении на ноль, если сигнал [`DivisionByZero`](https://python-all.ru/3.14/library/decimal.html#decimal.DivisionByZero) не перехвачен. Аналогично, если не перехвачен сигнал [`Overflow`](https://python-all.ru/3.14/library/decimal.html#decimal.Overflow), бесконечность может получиться при округлении за пределами наибольшего представимого числа.13331334Бесконечности являются знаковыми (аффинными) и могут использоваться в арифметических операциях, где они трактуются как очень большие неопределённые числа. Например, прибавление константы к бесконечности даёт другой бесконечный результат.13351336Некоторые операции являются неопределёнными и возвращают `NaN`, или, если сигнал [`InvalidOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.InvalidOperation) перехвачен, возбуждают исключение. Например, `0/0` возвращает `NaN`, что означает «не число». Этот вид `NaN` является тихим и, будучи созданным, будет распространяться через другие вычисления, всегда давая в результате `NaN`. Такое поведение может быть полезно для серии вычислений, в которых иногда отсутствуют входные данные – оно позволяет продолжить вычисления, помечая конкретные результаты как недействительные.13371338Существует вариант `sNaN`, который подаёт сигнал, а не остаётся тихим после каждой операции. Это полезное возвращаемое значение, когда недействительный результат должен прервать вычисления для специальной обработки.13391340Поведение операторов сравнения Python может быть несколько неожиданным, когда `NaN` участвует в сравнении. Проверка на равенство, где один из операндов является тихим или сигнальным `NaN`, всегда возвращает [`False`](https://python-all.ru/3.14/library/constants.html#False) (даже при выполнении `Decimal('NaN')==Decimal('NaN')`), а проверка на неравенство всегда возвращает [`True`](https://python-all.ru/3.14/library/constants.html#True). Попытка сравнить два Decimal с помощью любого из операторов `<`, `<=`, `>` или `>=` возбуждает сигнал [`InvalidOperation`](https://python-all.ru/3.14/library/decimal.html#decimal.InvalidOperation), если хотя бы один операнд является `NaN`, и возвращает `False`, если этот сигнал не перехвачен. Обратите внимание, что спецификация General Decimal Arithmetic не определяет поведение прямых сравнений; эти правила для сравнений, включающих `NaN`, взяты из стандарта IEEE 854 (см. Таблицу 3 в разделе 5.7). Для обеспечения строгого соответствия стандартам используйте вместо этого методы [`compare()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.compare) и [`compare_signal()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.compare_signal).13411342Знаковые нули могут возникать в результате вычислений, приводящих к исчерпанию. Они сохраняют знак, который получился бы, если бы вычисления выполнялись с большей точностью. Поскольку их величина равна нулю, положительный и отрицательный нули считаются равными, а их знак является информационным.13431344Помимо двух знаковых нулей, которые различны, но равны, существуют различные представления нуля с разной точностью, но эквивалентные по значению. К этому нужно немного привыкнуть. Для глаза, привыкшего к нормализованным представлениям с плавающей запятой, не сразу очевидно, что следующий расчёт возвращает значение, равное нулю:13451346```python1347>>> 1 / Decimal('Infinity')1348Decimal('0E-1000026')1349```13501351## Работа с потоками13521353Функция [`getcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.getcontext) обращается к разным объектам [`Context`](https://python-all.ru/3.14/library/decimal.html#decimal.Context) для каждого потока. Наличие отдельных контекстов потоков означает, что потоки могут вносить изменения (например, `getcontext().prec=10`), не мешая друг другу.13541355Аналогично, функция [`setcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.setcontext) автоматически назначает свою цель текущему потоку.13561357Если [`setcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.setcontext) не была вызвана до [`getcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.getcontext), то `getcontext()` автоматически создаёт новый контекст для использования в текущем потоке. Новые объекты контекста получают значения по умолчанию из объекта [`decimal.DefaultContext`](https://python-all.ru/3.14/library/decimal.html#decimal.DefaultContext).13581359Флаг [`sys.flags.thread_inherit_context`](https://python-all.ru/3.14/library/sys.html#sys.flags.thread_inherit_context) влияет на контекст для новых потоков. Если флаг ложен, новые потоки начнут работу с пустым контекстом. В этом случае [`getcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.getcontext) при вызове создаст новый объект контекста и будет использовать значения по умолчанию из *DefaultContext*. Если флаг истинен, новые потоки начнут с копии контекста от вызывающего [`threading.Thread.start()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.start).13601361Чтобы управлять значениями по умолчанию так, чтобы каждый поток использовал одни и те же значения во всём приложении, напрямую измените объект *DefaultContext*. Это следует сделать *до* запуска любых потоков, чтобы не возникло состояния гонки между потоками, вызывающими [`getcontext()`](https://python-all.ru/3.14/library/decimal.html#decimal.getcontext). Например:13621363```python1364# Установить глобальные настройки по умолчанию для всех потоков, которые будут запущены1365DefaultContext.prec = 121366DefaultContext.rounding = ROUND_DOWN1367DefaultContext.traps = ExtendedContext.traps.copy()1368DefaultContext.traps[InvalidOperation] = 11369setcontext(DefaultContext)13701371# После этого потоки можно запускать1372t1.start()1373t2.start()1374t3.start()1375 . . .1376```13771378## Рецепты13791380Вот несколько рецептов, которые служат вспомогательными функциями и демонстрируют способы работы с классом [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal):13811382```python1383def moneyfmt(value, places=2, curr='', sep=',', dp='.',1384 pos='', neg='-', trailneg=''):1385 """Преобразовать Decimal в строку, отформатированную как денежная сумма.13861387 places: обязательное количество знаков после десятичной точки1388 curr: необязательный символ валюты перед знаком (может быть пустым)1389 sep: необязательный разделитель групп (запятая, точка, пробел или пусто)1390 dp: указатель десятичной точки (запятая или точка)1391 указывать пустым только при places=01392 pos: необязательный знак для положительных чисел: '+', пробел или пусто1393 neg: необязательный знак для отрицательных чисел: '-', '(', пробел или пусто1394 trailneg:необязательный завершающий знак минуса: '-', ')', пробел или пусто13951396 >>> d = Decimal('-1234567.8901')1397 >>> moneyfmt(d, curr='$')1398 '-$1,234,567.89'1399 >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')1400 '1.234.568-'1401 >>> moneyfmt(d, curr='$', neg='(', trailneg=')')1402 '($1,234,567.89)'1403 >>> moneyfmt(Decimal(123456789), sep=' ')1404 '123 456 789.00'1405 >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')1406 '<0.02>'14071408 """1409 q = Decimal(10) ** -places # 2 знака после запятой --> '0.01'1410 sign, digits, exp = value.quantize(q).as_tuple()1411 result = []1412 digits = list(map(str, digits))1413 build, next = result.append, digits.pop1414 if sign:1415 build(trailneg)1416 for i in range(places):1417 build(next() if digits else '0')1418 if places:1419 build(dp)1420 if not digits:1421 build('0')1422 i = 01423 while digits:1424 build(next())1425 i += 11426 if i == 3 and digits:1427 i = 01428 build(sep)1429 build(curr)1430 build(neg if sign else pos)1431 return ''.join(reversed(result))14321433def pi():1434 """Вычислить число Пи с текущей точностью.14351436 >>> print(pi())1437 3.14159265358979323846264338314381439 """1440 getcontext().prec += 2 # дополнительные цифры для промежуточных шагов1441 three = Decimal(3) # подставить "three=3.0" вместо обычных чисел с плавающей точкой1442 lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 241443 while s != lasts:1444 lasts = s1445 n, na = n+na, na+81446 d, da = d+da, da+321447 t = (t * n) / d1448 s += t1449 getcontext().prec -= 21450 return +s # унарный плюс применяет новую точность14511452def exp(x):1453 """Возвращает e, возведённое в степень x. Тип результата соответствует типу входного значения.14541455 >>> print(exp(Decimal(1)))1456 2.7182818284590452353602874711457 >>> print(exp(Decimal(2)))1458 7.3890560989306502272304274611459 >>> print(exp(2.0))1460 7.389056098931461 >>> print(exp(2+0j))1462 (7.38905609893+0j)14631464 """1465 getcontext().prec += 21466 i, lasts, s, fact, num = 0, 0, 1, 1, 11467 while s != lasts:1468 lasts = s1469 i += 11470 fact *= i1471 num *= x1472 s += num / fact1473 getcontext().prec -= 21474 return +s14751476def cos(x):1477 """Возвращает косинус x, измеренного в радианах.14781479 Аппроксимация рядом Тейлора даёт наилучший результат при малых значениях x.1480 Для больших значений сначала вычислите x = x % (2 * pi).14811482 >>> print(cos(Decimal('0.5')))1483 0.87758256189037271611628158261484 >>> print(cos(0.5))1485 0.877582561891486 >>> print(cos(0.5+0j))1487 (0.87758256189+0j)14881489 """1490 getcontext().prec += 21491 i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 11492 while s != lasts:1493 lasts = s1494 i += 21495 fact *= i * (i-1)1496 num *= x * x1497 sign *= -11498 s += num / fact * sign1499 getcontext().prec -= 21500 return +s15011502def sin(x):1503 """Возвращает синус угла x, заданного в радианах.15041505 Аппроксимация рядом Тейлора даёт наилучший результат при малых значениях x.1506 Для больших значений сначала вычислите x = x % (2 * pi).15071508 >>> print(sin(Decimal('0.5')))1509 0.47942553860420300027328793521510 >>> print(sin(0.5))1511 0.4794255386041512 >>> print(sin(0.5+0j))1513 (0.479425538604+0j)15141515 """1516 getcontext().prec += 21517 i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 11518 while s != lasts:1519 lasts = s1520 i += 21521 fact *= i * (i-1)1522 num *= x * x1523 sign *= -11524 s += num / fact * sign1525 getcontext().prec -= 21526 return +s1527```15281529## Вопросы и ответы по Decimal15301531Вопрос: Неудобно каждый раз набирать `decimal.Decimal('1234.5')`. Есть ли способ сократить ввод в интерактивном интерпретаторе?15321533Некоторые пользователи сокращают конструктор до одной буквы:15341535```python1536>>> D = decimal.Decimal1537>>> D('1.23') + D('3.45')1538Decimal('4.68')1539```15401541Вопрос: В приложении с фиксированной запятой и двумя знаками после запятой одни исходные данные содержат много знаков и требуют округления, а другие не должны иметь лишних цифр и нуждаются в проверке. Какие методы следует использовать?15421543Метод [`quantize()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.quantize) округляет до заданного числа десятичных знаков. Если установлен перехват [`Inexact`](https://python-all.ru/3.14/library/decimal.html#decimal.Inexact), он также полезен для проверки:15441545```python1546>>> TWOPLACES = Decimal(10) ** -2 # то же, что Decimal('0.01')1547```15481549```python1550>>> # Округлить до двух знаков1551>>> Decimal('3.214').quantize(TWOPLACES)1552Decimal('3.21')1553```15541555```python1556>>> # Проверка, что число не выходит за пределы двух знаков1557>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))1558Decimal('3.21')1559```15601561```python1562>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))1563Traceback (most recent call last):1564 ...1565Inexact: None1566```15671568Вопрос: После получения корректных двухзначных входных данных как поддерживать это инвариантное свойство во всём приложении?15691570Некоторые операции, такие как сложение, вычитание и умножение на целое число, автоматически сохраняют фиксированную запятую. Другие операции, например деление и умножение на нецелое число, изменяют количество десятичных знаков, и за ними должен следовать шаг [`quantize()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.quantize):15711572```python1573>>> a = Decimal('102.72') # Начальные значения чисел с фиксированной точкой1574>>> b = Decimal('3.17')1575>>> a + b # Сложение сохраняет фиксированную точку1576Decimal('105.89')1577>>> a - b1578Decimal('99.55')1579>>> a * 42 # Умножение на целое число – тоже1580Decimal('4314.24')1581>>> (a * b).quantize(TWOPLACES) # Результат умножения на нецелое число нужно квантовать1582Decimal('325.62')1583>>> (b / a).quantize(TWOPLACES) # И квантовать результат деления1584Decimal('0.03')1585```15861587При разработке приложений с фиксированной запятой удобно определить функции для обработки шага [`quantize()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.quantize):15881589```python1590>>> def mul(x, y, fp=TWOPLACES):1591... return (x * y).quantize(fp)1592...1593>>> def div(x, y, fp=TWOPLACES):1594... return (x / y).quantize(fp)1595```15961597```python1598>>> mul(a, b) # Автоматически сохранять фиксированную точку1599Decimal('325.62')1600>>> div(b, a)1601Decimal('0.03')1602```16031604Вопрос: Существует много способов выразить одно и то же значение. Числа `200`, `200.000`, `2E2` и `.02E+4` имеют одинаковое значение при разной точности. Есть ли способ преобразовать их в единое узнаваемое каноническое значение?16051606Метод [`normalize()`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal.normalize) отображает все эквивалентные значения на единый представитель:16071608```python1609>>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())1610>>> [v.normalize() for v in values]1611[Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]1612```16131614Вопрос: Когда происходит округление в вычислениях?16151616Округление происходит *после* вычисления. Философия спецификации десятичных чисел заключается в том, что числа считаются точными и создаются независимо от текущего контекста. Они могут иметь даже большую точность, чем текущий контекст. Вычисления обрабатывают эти точные исходные данные, а затем к *результату* вычисления применяется округление (или другие контекстные операции):16171618```python1619>>> getcontext().prec = 51620>>> pi = Decimal('3.1415926535') # Более 5 цифр1621>>> pi # Все цифры сохраняются1622Decimal('3.1415926535')1623>>> pi + 0 # Округляется после сложения1624Decimal('3.1416')1625>>> pi - Decimal('0.00005') # Вычесть неокруглённые числа, затем округлить1626Decimal('3.1415')1627>>> pi + 0 - Decimal('0.00005'). # Промежуточные значения округляются1628Decimal('3.1416')1629```16301631Вопрос: Некоторые десятичные значения всегда выводятся в экспоненциальной записи. Можно ли получить представление без экспоненты?16321633Для некоторых значений экспоненциальная запись – единственный способ выразить количество значащих цифр в коэффициенте. Например, представление `5.0E+3` как `5000` сохраняет значение неизменным, но не отражает значимость двух знаков исходного числа.16341635Если приложению не важно отслеживать значимость, можно легко удалить экспоненту и хвостовые нули, потеряв значимость, но сохранив значение:16361637```python1638>>> def remove_exponent(d):1639... return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()1640```16411642```python1643>>> remove_exponent(Decimal('5E+3'))1644Decimal('5000')1645```16461647Вопрос: Можно ли преобразовать обычное число float в [`Decimal`](https://python-all.ru/3.14/library/decimal.html#decimal.Decimal)?16481649Да, любое двоичное число с плавающей запятой может быть точно выражено как Decimal, хотя точное преобразование может потребовать большей точности, чем можно предположить интуитивно:16501651```pycon1652>>> Decimal(math.pi)1653Decimal('3.141592653589793115997963468544185161590576171875')1654```16551656Вопрос: В сложных вычислениях как убедиться, что я не получил ложный результат из-за недостаточной точности или аномалий округления.16571658Модуль decimal упрощает проверку результатов. Рекомендуется повторять вычисления с большей точностью и различными режимами округления. Сильно различающиеся результаты указывают на недостаточную точность, проблемы с режимом округления, плохо обусловленные входные данные или численно неустойчивый алгоритм.16591660Вопрос: Я заметил, что точность контекста применяется к результатам операций, но не к входным данным. Есть ли какие-то особенности, на которые следует обратить внимание при смешивании значений разной точности?16611662Да. Принцип в том, что все значения считаются точными, и арифметика с ними тоже точна. Округляются только результаты. Преимущество для входных данных в том, что «что ввел, то и получил». Недостаток в том, что результаты могут выглядеть странно, если забыть, что входные данные не округлялись:16631664```pycon1665>>> getcontext().prec = 31666>>> Decimal('3.104') + Decimal('2.104')1667Decimal('5.21')1668>>> Decimal('3.104') + Decimal('0.000') + Decimal('2.104')1669Decimal('5.20')1670```16711672Решение – либо увеличить точность, либо принудительно округлить входные данные с помощью унарного плюса:16731674```pycon1675>>> getcontext().prec = 31676>>> +Decimal('1.23456789') # Унарный плюс вызывает округление1677Decimal('1.23')1678```16791680В качестве альтернативы входные данные можно округлить при создании с помощью метода [`Context.create_decimal()`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.create_decimal):16811682```python1683>>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')1684Decimal('1.2345')1685```16861687Вопрос: Реализация CPython быстра для больших чисел?16881689Да. В реализациях CPython и PyPy3 версии модуля decimal на C/CFFI включают высокоскоростную библиотеку [libmpdec](https://python-all.ru/3.14/library/decimal.html) для десятичной арифметики с плавающей запятой произвольной точности и корректным округлением [\[1\]](https://python-all.ru/3.14/library/decimal.html#id4). `libmpdec` использует [умножение Карацубы](https://python-all.ru/3.14/library/decimal.html) для чисел среднего размера и [теоретико-числовое преобразование](https://python-all.ru/3.14/library/decimal.html) для очень больших чисел.16901691Контекст необходимо адаптировать для точной арифметики произвольной точности. [`Emin`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Emin) и [`Emax`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.Emax) всегда должны быть установлены на максимальные значения, [`clamp`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.clamp) всегда должно быть 0 (по умолчанию). Установка [`prec`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.prec) требует осторожности.16921693Самый простой способ попробовать арифметику больших чисел – использовать максимальное значение как для [`prec`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.prec), так и для [\[2\]](https://python-all.ru/3.14/library/decimal.html#id5):16941695```python1696>>> setcontext(Context(prec=MAX_PREC, Emax=MAX_EMAX, Emin=MIN_EMIN))1697>>> x = Decimal(2) ** 2561698>>> x / 1281699Decimal('904625697166532776746648320380374280103671755200316906558262375061821325312')1700```17011702Для неточных результатов [`MAX_PREC`](https://python-all.ru/3.14/library/decimal.html#decimal.MAX_PREC) слишком велико на 64-битных платформах, и доступной памяти будет недостаточно:17031704```python1705>>> Decimal(1) / 31706Traceback (most recent call last):1707 File "<stdin>", line 1, in <module>1708MemoryError1709```17101711В системах с перераспределением (например, Linux) более сложный подход – настроить [`prec`](https://python-all.ru/3.14/library/decimal.html#decimal.Context.prec) в зависимости от объёма доступной оперативной памяти. Предположим, у вас 8 ГБ ОЗУ и ожидается 10 одновременных операндов, каждый максимум 500 МБ:17121713```python1714>>> import sys1715>>>1716>>> # Максимальное количество цифр для одного операнда при использовании 500 МБ в 8-байтовых словах1717>>> # с 19 цифрами на слово (4 байта и 9 цифр для 32-битной сборки):1718>>> maxdigits = 19 * ((500 * 1024**2) // 8)1719>>>1720>>> # Проверить, что это работает:1721>>> c = Context(prec=maxdigits, Emax=MAX_EMAX, Emin=MIN_EMIN)1722>>> c.traps[Inexact] = True1723>>> setcontext(c)1724>>>1725>>> # Заполнить доступную точность девятками:1726>>> x = Decimal(0).logical_invert() * 91727>>> sys.getsizeof(x)17285242881121729>>> x + 21730Traceback (most recent call last):1731 File "<stdin>", line 1, in <module>1732 decimal.Inexact: [<class 'decimal.Inexact'>]1733```17341735В общем случае (и особенно в системах без перераспределения) рекомендуется оценить ещё более жёсткие границы и установить перехват [`Inexact`](https://python-all.ru/3.14/library/decimal.html#decimal.Inexact), если ожидается, что все вычисления будут точными.17361737\[[1](https://python-all.ru/3.14/library/decimal.html#id2)\]17381739Добавлено в версии 3.3.17401741\[[2](https://python-all.ru/3.14/library/decimal.html#id3)\]17421743Изменено в версии 3.9: Этот подход теперь работает для всех точных результатов, кроме нецелых степеней.1744