# `decimal` — Aritmética de ponto fixo decimal e ponto flutuante

Código-fonte: Lib/decimal.py

O módulo `decimal` fornece suporte a aritmética rápida de ponto flutuante decimal corretamente arredondado. Oferece várias vantagens sobre o tipo de dados `float`:

- Decimal “é baseado em um modelo de ponto flutuante que foi projetado com as pessoas em mente e necessariamente tem um princípio orientador primordial – os computadores devem fornecer uma aritmética que funcione da mesma maneira que a aritmética que as pessoas aprendem na escola”. – trecho da especificação aritmética decimal.

- Os números decimais podem ser representados exatamente. Por outro lado, números como `1.1` e `2.2` não possuem representações exatas em ponto flutuante binário. Os usuários finais normalmente não esperam que `1.1 + 2.2` sejam exibidos como `3.3000000000000003`, como acontece com o ponto flutuante binário.

- A exatidão transita para a aritmética. No ponto flutuante decimal, `0.1 + 0.1 + 0.1 - 0.3` é exatamente igual a zero. No ponto flutuante binário, o resultado é `5.5511151231257827e-017`. Embora próximas de zero, as diferenças impedem o teste de igualdade confiável e as diferenças podem se acumular. Por esse motivo, o decimal é preferido em aplicações de contabilidade que possuem invariáveis estritos de igualdade.

- O módulo decimal incorpora uma noção de casas significativas para que `1.30 + 1.20` seja `2.50`. O zero à direita é mantido para indicar significância. Esta é a apresentação habitual para aplicações monetárias. Para multiplicação, a abordagem “livro escolar” usa todas as figuras nos multiplicandos. Por exemplo, `1.3 * 1.2` é igual a `1.56` enquanto `1.30 * 1.20` é igual a `1.5600`.

- Diferentemente do ponto flutuante binário baseado em hardware, o módulo decimal possui uma precisão alterável pelo usuário (padrão de 28 casas), que pode ser tão grande quanto necessário para um determinado problema:

      >>> from decimal import *
      >>> getcontext().prec = 6
      >>> Decimal(1) / Decimal(7)
      Decimal('0.142857')
      >>> getcontext().prec = 28
      >>> Decimal(1) / Decimal(7)
      Decimal('0.1428571428571428571428571429')

- O ponto flutuante binário e decimal é implementado em termos de padrões publicados. Enquanto o tipo ponto flutuante embutido expõe apenas uma parte modesta de seus recursos, o módulo decimal expõe todas as partes necessárias do padrão. Quando necessário, o programador tem controle total sobre o arredondamento e o manuseio do sinal. Isso inclui uma opção para impor aritmética exata usando exceções para bloquear quaisquer operações inexatas.

- O módulo decimal foi projetado para dar suporte, “sem prejuízo, a aritmética decimal não arredondada exata (às vezes chamada aritmética de ponto fixo) e aritmética arredondada de ponto flutuante”. – trecho da especificação aritmética decimal.

O design do módulo é centrado em torno de três conceitos: o número decimal, o contexto da aritmética e os sinais.

Um número decimal é imutável. Possui um sinal, dígitos de coeficiente e um expoente. Para preservar a significância, os dígitos do coeficiente não truncam zeros à direita. Os decimais também incluem valores especiais, tais como `Infinity`, `-Infinity` e `NaN`. O padrão também diferencia `-0` de `+0`.

O contexto da aritmética é um ambiente que especifica precisão, regras de arredondamento, limites de expoentes, sinalizadores indicando os resultados das operações e ativadores de interceptação que determinam se os sinais são tratados como exceções. As opções de arredondamento incluem `ROUND_CEILING`, `ROUND_DOWN`, `ROUND_FLOOR`, `ROUND_HALF_DOWN`, `ROUND_HALF_EVEN`, `ROUND_HALF_UP`, `ROUND_UP` e `ROUND_05UP`.

Sinais são grupos de condições excepcionais que surgem durante o curso da computação. Dependendo das necessidades da aplicação, os sinais podem ser ignorados, considerados informativos ou tratados como exceções. Os sinais no módulo decimal são: `Clamped`, `InvalidOperation`, `DivisionByZero`, `Inexact`, `Rounded`, `Subnormal`, `Overflow`, `Underflow` e `FloatOperation`.

Para cada sinal, há um sinalizador e um ativador de interceptação. Quando um sinal é encontrado, seu sinalizador é definido como um e, se o ativador de interceptação estiver definido como um, uma exceção será gerada. Os sinalizadores são fixos; portanto, o usuário precisa redefini-los antes de monitorar um cálculo.

Ver também

- A especificação geral aritmética decimal da IBM, The General Decimal Arithmetic Specification.

## Tutorial de início rápido

O início usual do uso de decimais é importar o módulo, exibir o contexto atual com `getcontext()` e, se necessário, definir novos valores para precisão, arredondamento ou armadilhas ativados:

    >>> from decimal import *
    >>> getcontext()
    Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
            capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero,
            InvalidOperation])

    >>> getcontext().prec = 7       # Define uma nova precisão

Instâncias decimais podem ser construídas a partir de números inteiros, strings, pontos flutuantes ou tuplas. A construção de um número inteiro ou de um ponto flutuante realiza uma conversão exata do valor desse número inteiro ou ponto flutuante. Os números decimais incluem valores especiais como `NaN`, que significa “Não é um número”, `Infinity` positivo e negativo e `-0`:

    >>> getcontext().prec = 28
    >>> Decimal(10)
    Decimal('10')
    >>> Decimal('3.14')
    Decimal('3.14')
    >>> Decimal(3.14)
    Decimal('3.140000000000000124344978758017532527446746826171875')
    >>> Decimal((0, (3, 1, 4), -2))
    Decimal('3.14')
    >>> Decimal(str(2.0 ** 0.5))
    Decimal('1.4142135623730951')
    >>> Decimal(2) ** Decimal('0.5')
    Decimal('1.414213562373095048801688724')
    >>> Decimal('NaN')
    Decimal('NaN')
    >>> Decimal('-Infinity')
    Decimal('-Infinity')

Se o sinal `FloatOperation` for capturado na armadilha, a mistura acidental de decimais e pontos flutuantes em construtores ou comparações de ordenação levanta uma exceção:

    >>> c = getcontext()
    >>> c.traps[FloatOperation] = True
    >>> Decimal(3.14)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
    >>> Decimal('3.5') < 3.7
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
    >>> Decimal('3.5') == 3.5
    True

Adicionado na versão 3.3.

O significado de um novo decimal é determinado apenas pelo número de dígitos inseridos. A precisão e o arredondamento do contexto só entram em jogo durante operações aritméticas.

    >>> getcontext().prec = 6
    >>> Decimal('3.0')
    Decimal('3.0')
    >>> Decimal('3.1415926535')
    Decimal('3.1415926535')
    >>> Decimal('3.1415926535') + Decimal('2.7182818285')
    Decimal('5.85987')
    >>> getcontext().rounding = ROUND_UP
    >>> Decimal('3.1415926535') + Decimal('2.7182818285')
    Decimal('5.85988')

Se os limites internos da versão C forem excedidos, a construção de um decimal levanta `InvalidOperation`:

    >>> Decimal("1e9999999999999999999")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

Alterado na versão 3.3.

Os decimais interagem bem com grande parte do resto do Python. Aqui está um pequeno circo voador de ponto flutuante decimal:

    >>> data = list(map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()))
    >>> max(data)
    Decimal('9.25')
    >>> min(data)
    Decimal('0.03')
    >>> sorted(data)
    [Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),
     Decimal('2.35'), Decimal('3.45'), Decimal('9.25')]
    >>> sum(data)
    Decimal('19.29')
    >>> a,b,c = data[:3]
    >>> str(a)
    '1.34'
    >>> float(a)
    1.34
    >>> round(a, 1)
    Decimal('1.3')
    >>> int(a)
    1
    >>> a * 5
    Decimal('6.70')
    >>> a * b
    Decimal('2.5058')
    >>> c % a
    Decimal('0.77')

E algumas funções matemáticas também estão disponíveis no Decimal:

    >>> getcontext().prec = 28
    >>> Decimal(2).sqrt()
    Decimal('1.414213562373095048801688724')
    >>> Decimal(1).exp()
    Decimal('2.718281828459045235360287471')
    >>> Decimal('10').ln()
    Decimal('2.302585092994045684017991455')
    >>> Decimal('10').log10()
    Decimal('1')

O método `quantize()` arredonda um número para um expoente fixo. Esse método é útil para aplicações monetárias que geralmente arredondam os resultados para um número fixo de locais:

    >>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
    Decimal('7.32')
    >>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
    Decimal('8')

Como mostrado acima, a função `getcontext()` acessa o contexto atual e permite que as configurações sejam alteradas. Essa abordagem atende às necessidades da maioria das aplicações.

Para trabalhos mais avançados, pode ser útil criar contextos alternativos usando o construtor Context(). Para ativar uma alternativa, use a função `setcontext()`.

De acordo com o padrão, o módulo `decimal` fornece dois contextos padrão prontos para uso, `BasicContext` e `ExtendedContext`. O primeiro é especialmente útil para depuração porque muitas das armadilhas estão ativadas:

    >>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
    >>> setcontext(myothercontext)
    >>> Decimal(1) / Decimal(7)
    Decimal('0.142857142857142857142857142857142857142857142857142857142857')

    >>> ExtendedContext
    Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
            capitals=1, clamp=0, flags=[], traps=[])
    >>> setcontext(ExtendedContext)
    >>> Decimal(1) / Decimal(7)
    Decimal('0.142857143')
    >>> Decimal(42) / Decimal(0)
    Decimal('Infinity')

    >>> setcontext(BasicContext)
    >>> Decimal(42) / Decimal(0)
    Traceback (most recent call last):
      File "<pyshell#143>", line 1, in -toplevel-
        Decimal(42) / Decimal(0)
    DivisionByZero: x / 0

Os contextos também possuem sinalizadores para monitorar condições excepcionais encontradas durante os cálculos. Os sinalizadores permanecem definidos até que sejam explicitamente limpos, portanto, é melhor limpar os sinalizadores antes de cada conjunto de cálculos monitorados usando o método `clear_flags()`.

    >>> setcontext(ExtendedContext)
    >>> getcontext().clear_flags()
    >>> Decimal(355) / Decimal(113)
    Decimal('3.14159292')
    >>> getcontext()
    Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
            capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[])

A entrada flags mostra que a aproximação racional de pi foi arredondada (dígitos além da precisão do contexto foram descartados) e que o resultado é inexato (alguns dos dígitos descartados eram diferentes de zero).

As armadilhas individuais são definidas usando o dicionário no atributo `traps` de um contexto:

    >>> setcontext(ExtendedContext)
    >>> Decimal(1) / Decimal(0)
    Decimal('Infinity')
    >>> getcontext().traps[DivisionByZero] = 1
    >>> Decimal(1) / Decimal(0)
    Traceback (most recent call last):
      File "<pyshell#112>", line 1, in -toplevel-
        Decimal(1) / Decimal(0)
    DivisionByZero: x / 0

A maioria dos programas ajusta o contexto atual apenas uma vez, no início do programa. E, em muitas aplicações, os dados são convertidos para `Decimal` com uma única conversão dentro de um loop. Com o conjunto de contextos e decimais criados, a maior parte do programa manipula os dados de maneira diferente do que com outros tipos numéricos do Python.

## Objetos de Decimal

class decimal.Decimal(value='0', context=None)

  Constrói um novo objeto de `Decimal` com base em value.

  value pode ser um inteiro, string, tupla, `float` ou outro objeto de `Decimal`. Se nenhum value for fornecido, retornará `Decimal('0')`. Se value for uma string, ele deverá estar em conformidade com a sintaxe da string numérica decimal após caracteres de espaço em branco à esquerda e à direita, bem como sublinhados em toda parte, serem removidos:

      sign           ::=  '+' | '-'
      digit          ::=  '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
      indicator      ::=  'e' | 'E'
      digits         ::=  digit [digit]...
      decimal-part   ::=  digits '.' [digits] | ['.'] digits
      exponent-part  ::=  indicator [sign] digits
      infinity       ::=  'Infinity' | 'Inf'
      nan            ::=  'NaN' [digits] | 'sNaN' [digits]
      numeric-value  ::=  decimal-part [exponent-part] | infinity
      numeric-string ::=  [sign] numeric-value | [sign] nan

  Outros dígitos decimais Unicode também são permitidos onde `digit` aparece acima. Isso inclui dígitos decimais de vários outros alfabetos (por exemplo, dígitos em árabes-índicos e devanágaris), além dos dígitos de largura total `'\uff10'` a `'\uff19'`. A capitalização não é significativa, então, por exemplo, `inf`, `Inf`, `INFINITY` e `iNfINity` são todas grafias aceitáveis ​​para infinito positivo.

  Se value for um `tuple`, ele deverá ter três componentes, um sinal (`0` para positivo ou `1` para negativo), um `tuple` de dígitos e um expoente inteiro. Por exemplo, `Decimal((0, (1, 4, 1, 4), -3))` returna `Decimal('1.414')`.

  Se value é um `float`, o valor do ponto flutuante binário é convertido sem perdas no seu equivalente decimal exato. Essa conversão geralmente requer 53 ou mais dígitos de precisão. Por exemplo, `Decimal(float('1.1'))` converte para `Decimal('1.100000000000000088817841970012523233890533447265625')`.

  A precisão context não afeta quantos dígitos estão armazenados. Isso é determinado exclusivamente pelo número de dígitos em value. Por exemplo, `Decimal('3.00000')` registra todos os cinco zeros, mesmo que a precisão do contexto seja apenas três.

  O objetivo do argumento context é determinar o que fazer se value for uma string malformada. Se o contexto capturar `InvalidOperation`, uma exceção será levantada; caso contrário, o construtor retornará um novo decimal com o valor de `NaN`.

  Uma vez construídos, objetos de `Decimal` são imutáveis.

  Alterado na versão 3.2: O argumento para o construtor agora pode ser uma instância de `float`.

  Alterado na versão 3.3: Os argumentos de `float` levantam uma exceção se a armadilha `FloatOperation` estiver definida. Por padrão, a armadilha está desativada.

  Alterado na versão 3.6: Sublinhados são permitidos para agrupamento, como nos literais de ponto flutuante e integral no código.

  Objetos decimais de ponto flutuante compartilham muitas propriedades com outros tipos numéricos embutidos, como `float` e `int`. Todas as operações matemáticas usuais e métodos especiais se aplicam. Da mesma forma, objetos decimais podem ser copiados, separados, impressos, usados como chaves de dicionário, usados como elementos de conjunto, comparados, classificados e convertidos a outro tipo (como `float` ou `int`).

  Existem algumas pequenas diferenças entre aritmética em objetos decimais e aritmética em números inteiros e flutuantes. Quando o operador de resto `%` é aplicado a objetos decimais, o sinal do resultado é o sinal do dividend em vez do sinal do divisor:

      >>> (-7) % 4
      1
      >>> Decimal(-7) % Decimal(4)
      Decimal('-3')

  O operador de divisão inteira `//` se comporta de maneira análoga, retornando a parte inteira do quociente verdadeiro (truncando em direção a zero) em vez de seu resto, de modo a preservar a identidade usual `x == (x // y) * y + x % y`:

      >>> -7 // 4
      -2
      >>> Decimal(-7) // Decimal(4)
      Decimal('-1')

  Os operadores `%` e `//` implementam as operações de `remainder` e `divide-integer` (respectivamente) como descrito na especificação.

  Objetos decimais geralmente não podem ser combinados com pontos flutuantes ou instâncias de `fractions.Fraction` em operações aritméticas: uma tentativa de adicionar um `Decimal` a um `float`, por exemplo, vai levantar um `TypeError`. No entanto, é possível usar os operadores de comparação do Python para comparar uma instância de `Decimal` `x` com outro número `y`. Isso evita resultados confusos ao fazer comparações de igualdade entre números de tipos diferentes.

  Alterado na versão 3.2: As comparações de tipos mistos entre instâncias de `Decimal` e outros tipos numéricos agora são totalmente suportadas.

  Além das propriedades numéricas padrões, os objetos de ponto flutuante decimal também possuem vários métodos especializados:

  adjusted()

    Retorna o expoente ajustado depois de deslocar os dígitos mais à direita do coeficiente até restar apenas o dígito principal: `Decimal('321e+5').adjusted()` retorna sete. Usado para determinar a posição do dígito mais significativo em relação ao ponto decimal.

  as_integer_ratio()

    Retorna um par `(n, d)` de números inteiros que representam a instância dada `Decimal` como uma fração, nos termos mais baixos e com um denominador positivo:

        >>> Decimal('-3.14').as_integer_ratio()
        (-157, 50)

    A conversão é exata. Levanta OverflowError em infinitos e ValueError em NaNs.

  Adicionado na versão 3.6.

  as_tuple()

    Retorna uma representação de tupla nomeada do número: `DecimalTuple(sign, digits, exponent)`.

  canonical()

    Retorna a codificação canônica do argumento. Atualmente, a codificação de uma instância de `Decimal` é sempre canônica, portanto, esta operação retorna seu argumento inalterado.

  compare(other, context=None)

    Compara os valores de duas instâncias decimais. `compare()` retorna uma instância decimal, e se qualquer operando for um NaN, o resultado será um NaN:

        a or b is a NaN  ==> Decimal('NaN')
        a < b            ==> Decimal('-1')
        a == b           ==> Decimal('0')
        a > b            ==> Decimal('1')

  compare_signal(other, context=None)

    Esta operação é idêntica ao método `compare()`, exceto que todos os NaNs sinalizam. Ou seja, se nenhum operando for um NaN sinalizador, qualquer operando NaN silencioso será tratado como se fosse um NaN sinalizador.

  compare_total(other, context=None)

    Compara dois operandos usando sua representação abstrata em vez de seu valor numérico. Semelhante ao método `compare()`, mas o resultado fornece uma ordem total nas instâncias de `Decimal`. Duas instâncias de `Decimal` com o mesmo valor numérico, mas diferentes representações, se comparam desiguais nesta ordem:

        >>> Decimal('12.0').compare_total(Decimal('12'))
        Decimal('-1')

    Os NaNs silenciosos e sinalizadores também estão incluídos no pedido total. O resultado dessa função é `Decimal('0')` se os dois operandos tiverem a mesma representação, `Decimal('-1')` se o primeiro operando for menor na ordem total que o segundo e `Decimal('1')` se o primeiro operando for maior na ordem total que o segundo operando. Veja a especificação para detalhes da ordem total.

    Esta operação não é afetada pelo contexto e é silenciosa: nenhum sinalizador é alterado e nenhum arredondamento é executado. Como uma exceção, a versão C pode levantar InvalidOperation se o segundo operando não puder ser convertido exatamente.

  compare_total_mag(other, context=None)

    Compara dois operandos usando sua representação abstrata em vez de seu valor, como em `compare_total()`, mas ignorando o sinal de cada operando. `x.compare_total_mag(y)` é equivalente a `x.copy_abs().compare_total(y.copy_abs())`.

    Esta operação não é afetada pelo contexto e é silenciosa: nenhum sinalizador é alterado e nenhum arredondamento é executado. Como uma exceção, a versão C pode levantar InvalidOperation se o segundo operando não puder ser convertido exatamente.

  conjugate()

    Apenas retorna a si próprio, sendo esse método apenas para atender à Especificação de Decimal.

  copy_abs()

    Retorna o valor absoluto do argumento. Esta operação não é afetada pelo contexto e é silenciosa: nenhum sinalizador é alterado e nenhum arredondamento é executado.

  copy_negate()

    Retorna a negação do argumento. Esta operação não é afetada pelo contexto e é silenciosa: nenhum sinalizador é alterado e nenhum arredondamento é executado.

  copy_sign(other, context=None)

    Retorna uma cópia do primeiro operando com o sinal definido para ser o mesmo que o sinal do segundo operando. Por exemplo:

        >>> Decimal('2.3').copy_sign(Decimal('-1.5'))
        Decimal('-2.3')

    Esta operação não é afetada pelo contexto e é silenciosa: nenhum sinalizador é alterado e nenhum arredondamento é executado. Como uma exceção, a versão C pode levantar InvalidOperation se o segundo operando não puder ser convertido exatamente.

  exp(context=None)

    Retorna o valor da função exponencial (natural) `e**x` no número especificado. O resultado é arredondado corretamente usando o modo de arredondamento `ROUND_HALF_EVEN`.

        >>> Decimal(1).exp()
        Decimal('2.718281828459045235360287471')
        >>> Decimal(321).exp()
        Decimal('2.561702493119680037517373933E+139')

  classmethod from_float(f)

    Construtor alternativo que aceita apenas instâncias de `float` ou `int`.

    Observe que `Decimal.from_float(0.1)` não é o mesmo que `Decimal('0.1')`. Como 0.1 não é exatamente representável no ponto flutuante binário, o valor é armazenado como o valor representável mais próximo que é `0x1.999999999999ap-4`.; Esse valor equivalente em decimal é `0.1000000000000000055511151231257827021181583404541015625`.

    Nota

    A partir do Python 3.2 em diante, uma instância de `Decimal` também pode ser construída diretamente a partir de um `float`.

        >>> Decimal.from_float(0.1)
        Decimal('0.1000000000000000055511151231257827021181583404541015625')
        >>> Decimal.from_float(float('nan'))
        Decimal('NaN')
        >>> Decimal.from_float(float('inf'))
        Decimal('Infinity')
        >>> Decimal.from_float(float('-inf'))
        Decimal('-Infinity')

    Adicionado na versão 3.1.

  classmethod from_number(number)

    Construtor alternativo que aceita apenas instâncias de `float`, `int` ou `Decimal`, mas não strings ou tuplas.

        >>> Decimal.from_number(314)
        Decimal('314')
        >>> Decimal.from_number(0.1)
        Decimal('0.1000000000000000055511151231257827021181583404541015625')
        >>> Decimal.from_number(Decimal('3.14'))
        Decimal('3.14')

    Adicionado na versão 3.14.

  fma(other, third, context=None)

    Multiplicação e adição fundidos. Retorna self*other+third sem arredondamento do produto intermediário self*other.

        >>> Decimal(2).fma(3, 5)
        Decimal('11')

  is_canonical()

    Retorna `True` se o argumento for canônico e `False` caso contrário. Atualmente, uma instância de `Decimal` é sempre canônica, portanto, esta operação sempre retorna `True`.

  is_finite()

    Retorna `True` se o argumento for um número finito e `False` se o argumento for um infinito ou um NaN.

  is_infinite()

    Retorna `True` se o argumento for infinito positivo ou negativo e `False` caso contrário.

  is_nan()

    Retorna `True` se o argumento for NaN (silencioso ou sinalizador) e `False` caso contrário.

  is_normal(context=None)

    Retorna `True` se o argumento for um número finito normal. Retorna `False` se o argumento for zero, subnormal, infinito ou NaN.

  is_qnan()

    Retorna `True` se o argumento for um NaN silencioso, e `False` caso contrário.

  is_signed()

    Retorna `True` se o argumento tiver um sinal negativo e `False` caso contrário. Observe que zeros e NaNs podem carregar sinais.

  is_snan()

    Retorna `True` se o argumento for um sinal NaN e `False` caso contrário.

  is_subnormal(context=None)

    Retorna `True` se o argumento for subnormal e `False` caso contrário.

  is_zero()

    Retorna `True` se o argumento for um zero (positivo ou negativo) e `False` caso contrário.

  ln(context=None)

    Retorna o logaritmo (base e) natural do operando. O resultado é arredondado corretamente usando o modo de arredondamento `ROUND_HALF_EVEN`.

  log10(context=None)

    Retorna o logaritmo da base dez do operando. O resultado é arredondado corretamente usando o modo de arredondamento `ROUND_HALF_EVEN`.

  logb(context=None)

    Para um número diferente de zero, retorna o expoente ajustado de seu operando como uma instância de `Decimal`. Se o operando é zero, `Decimal('-Infinity')` é retornado e o sinalizador `DivisionByZero` é levantado. Se o operando for um infinito, `Decimal('Infinity')` será retornado.

  logical_and(other, context=None)

    `logical_and()` é uma operação lógica que leva dois operandos lógicos (consulte Operandos lógicos). O resultado é o `and` dígito a dígito dos dois operandos.

  logical_invert(context=None)

    `logical_invert()` é uma operação lógica. O resultado é a inversão dígito a dígito do operando.

  logical_or(other, context=None)

    `logical_or()` é uma operação lógica que leva dois operandos lógicos (consulte Operandos lógicos). O resultado é o `or` dígito a dígito dos dois operandos.

  logical_xor(other, context=None)

    `logical_xor()` é uma operação lógica que leva dois operandos lógicos (consulte Operandos lógicos). O resultado é o “ou exclusivo” dígito a dígito ou dos dois operandos.

  max(other, context=None)

    Como `max(self, other)`, exceto que a regra de arredondamento de contexto é aplicada antes de retornar e que os valores `NaN` são sinalizados ou ignorados (dependendo do contexto e se estão sinalizando ou silenciosos).

  max_mag(other, context=None)

    Semelhante ao método `max()`, mas a comparação é feita usando os valores absolutos dos operandos.

  min(other, context=None)

    Como `min(self, other)`, exceto que a regra de arredondamento de contexto é aplicada antes de retornar e que os valores `NaN` são sinalizados ou ignorados (dependendo do contexto e se estão sinalizando ou silenciosos).

  min_mag(other, context=None)

    Semelhante ao método `min()`, mas a comparação é feita usando os valores absolutos dos operandos.

  next_minus(context=None)

    Retorna o maior número representável no contexto fornecido (ou no contexto atual da thread, se nenhum contexto for fornecido) que seja menor que o operando especificado.

  next_plus(context=None)

    Retorna o menor número representável no contexto fornecido (ou no contexto atual da thread, se nenhum contexto for fornecido) que seja maior que o operando fornecido.

  next_toward(other, context=None)

    Se os dois operandos forem desiguais, retorna o número mais próximo ao primeiro operando na direção do segundo operando. Se os dois operandos forem numericamente iguais, retorna uma cópia do primeiro operando com o sinal configurado para ser o mesmo que o sinal do segundo operando.

  normalize(context=None)

    Usado para produzir valores canônicos de uma classe de equivalência no contexto atual ou no contexto especificado.

    Esta tem a mesma semântica que a operação unária mais, exceto que se o resultado final for finito, ele será reduzido à sua forma mais simples, com todos os zeros à direita removidos e seu sinal preservado. Ou seja, enquanto o coeficiente for diferente de zero e múltiplo de dez, o coeficiente é dividido por dez e o expoente é incrementado em 1. Caso contrário (o coeficiente é zero), o expoente é definido como 0. Em todos os casos, o sinal permanece inalterado. .

    Por exemplo, `Decimal('32.100')` e `Decimal('0.321000e+2')` ambos normalizam para o valor equivalente `Decimal('32.1')`.

    Observe que o arredondamento é aplicado antes de reduzir para a forma mais simples.

    Nas versões mais recentes da especificação, esta operação também é conhecida como `reduce`.

  number_class(context=None)

    Retorna uma string descrevendo a classe do operando. O valor retornado é uma das dez sequências a seguir.

    - `"-Infinity"`, indicando que o operando é infinito negativo.

    - `"-Normal"`, indicando que o operando é um número normal negativo.

    - `"-Subnormal"`, indicando que o operando é negativo e subnormal.

    - `"-Zero"`, indicando que o operando é um zero negativo.

    - `"+Zero"`, indicando que o operando é um zero positivo.

    - `"+Subnormal"`, indicando que o operando é positivo e subnormal.

    - `"+Normal"`, indicando que o operando é um número normal positivo.

    - `"+Infinity"`, indicando que o operando é infinito positivo.

    - `"NaN"`, indicando que o operando é um NaN (“Not a Number”) silencioso.

    - `"sNaN"`, indicando que o operando é um NaN sinalizador.

  quantize(exp, rounding=None, context=None)

    Retorna um valor igual ao primeiro operando após o arredondamento e com o expoente do segundo operando.

        >>> Decimal('1.41421356').quantize(Decimal('1.000'))
        Decimal('1.414')

    Diferentemente de outras operações, se o comprimento do coeficiente após a operação de quantização for maior que a precisão, então `InvalidOperation` é sinalizado. Isso garante que, a menos que haja uma condição de erro, o expoente quantizado é sempre igual ao do operando do lado direito.

    Também, diferentemente de outras operações, a quantização nunca sinaliza Underflow, mesmo que o resultado seja subnormal e inexato.

    Se o expoente do segundo operando for maior que o do primeiro, o arredondamento poderá ser necessário. Nesse caso, o modo de arredondamento é determinado pelo argumento `rounding`, se fornecido, ou pelo argumento `context` fornecido; se nenhum argumento for fornecido, o modo de arredondamento do contexto da thread atual será usado.

    Um erro é retornado sempre que o expoente resultante for maior que `Emax` ou menor que `Etiny()`.

  radix()

    Retorna `Decimal(10)`, a raiz (base) na qual a classe `Decimal` faz toda a sua aritmética. Incluído para compatibilidade com a especificação.

  remainder_near(other, context=None)

    Retorna o resto da divisão de self por other. Isso é diferente de `self % other`, pois o sinal do resto é escolhido para minimizar seu valor absoluto. Mais precisamente, o valor de retorno é `self - n * other`, onde `n` é o número inteiro mais próximo do valor exato de `self / other`, e se dois números inteiros estiverem igualmente próximos, o par será é escolhido.

    Se o resultado for zero, seu sinal será o sinal de self.

        >>> Decimal(18).remainder_near(Decimal(10))
        Decimal('-2')
        >>> Decimal(25).remainder_near(Decimal(10))
        Decimal('5')
        >>> Decimal(35).remainder_near(Decimal(10))
        Decimal('-5')

  rotate(other, context=None)

    Retorna o resultado da rotação dos dígitos do primeiro operando em uma quantidade especificada pelo segundo operando. O segundo operando deve ser um número inteiro no intervalo - precisão através da precisão. O valor absoluto do segundo operando fornece o número de locais a serem rotacionados. Se o segundo operando for positivo, a rotação será para a esquerda; caso contrário, a rotação será para a direita. O coeficiente do primeiro operando é preenchido à esquerda com zeros na precisão do comprimento, se necessário. O sinal e o expoente do primeiro operando não são alterados.

  same_quantum(other, context=None)

    Testa se “self” e “other” têm o mesmo expoente ou se ambos são `NaN`.

    Esta operação não é afetada pelo contexto e é silenciosa: nenhum sinalizador é alterado e nenhum arredondamento é executado. Como uma exceção, a versão C pode levantar InvalidOperation se o segundo operando não puder ser convertido exatamente.

  scaleb(other, context=None)

    Retorna o primeiro operando com o expoente ajustado pelo segundo. Da mesma forma, retorna o primeiro operando multiplicado por `10**other`. O segundo operando deve ser um número inteiro.

  shift(other, context=None)

    Retorna o resultado da troca dos dígitos do primeiro operando em uma quantidade especificada pelo segundo operando. O segundo operando deve ser um número inteiro no intervalo - precisão através da precisão. O valor absoluto do segundo operando fornece o número de locais a serem deslocados. Se o segundo operando for positivo, o deslocamento será para a esquerda; caso contrário, a mudança é para a direita. Os dígitos deslocados para o coeficiente são zeros. O sinal e o expoente do primeiro operando não são alterados.

  sqrt(context=None)

    Retorna a raiz quadrada do argumento para a precisão total.

  to_eng_string(context=None)

    Converte em uma string, usando notação de engenharia, se for necessário um expoente.

    A notação de engenharia possui um expoente que é múltiplo de 3. Isso pode deixar até 3 dígitos à esquerda da casa decimal e pode exigir a adição de um ou dois zeros à direita.

    Por exemplo, isso converte `Decimal('123E+1')` para `Decimal('1.23E+3')`.

  to_integral(rounding=None, context=None)

    Idêntico ao método `to_integral_value()`. O nome `to_integral` foi mantido para compatibilidade com versões mais antigas.

  to_integral_exact(rounding=None, context=None)

    Arredonda para o número inteiro mais próximo, sinalizando `Inexact` ou `Rounded`, conforme apropriado, se o arredondamento ocorrer. O modo de arredondamento é determinado pelo parâmetro `rounding`, se fornecido, ou pelo `context` especificado. Se nenhum parâmetro for fornecido, o modo de arredondamento do contexto atual será usado.

  to_integral_value(rounding=None, context=None)

    Arredonda para o número inteiro mais próximo sem sinalizar `Inexact` ou `Rounding`. Se fornecido, aplica rounding; caso contrário, usa o método de arredondamento no context especificado ou no contexto atual.

  Os números decimais podem ser arredondados usando a função `round()`:

  round(number)
  round(number, ndigits)

    Se ndigits não for fornecido ou `None`, retorna o `int` de number mais próximo, arredondando até chegar em par, e ignorando o modo de arredondamento do contexto `Decimal`. Levanta `OverflowError` se number for um infinito ou `ValueError` se for um NaN (silencioso ou de sinalização).

    Se ndigits for um `int`, o modo de arredondamento do contexto é respeitado e um `Decimal` representando número arredondado para o múltiplo mais próximo de `Decimal('1E-ndigits')` é retornado; neste caso, `round(number, ndigits)` é equivalente a `self.quantize(Decimal('1E-ndigits'))`. Retorna `Decimal('NaN')` se number for um NaN silencioso. Levanta `InvalidOperation` se number for um infinito, uma sinalização NaN, ou se o comprimento do coeficiente após a operação de quantização for maior que a precisão do contexto atual. Em outras palavras, para os situações comuns:

    - se ndigits for positivo, retorna number arredondado para ndigits casas decimais;

    - se ndigits for zero, retorna number arredondado para o número inteiro mais próximo;

    - se ndigits for negativo, retorna number arredondado para o múltiplo mais próximo de `10**abs(ndigits)`.

    Por exemplo:

        >>> from decimal import Decimal, getcontext, ROUND_DOWN
        >>> getcontext().rounding = ROUND_DOWN
        >>> round(Decimal('3.75'))     # arredondamento de contexto ignorado
        4
        >>> round(Decimal('3.5'))      # arredondamento para par mais próximo
        4
        >>> round(Decimal('3.75'), 0)  # usa o arredondamento de contexto
        Decimal('3')
        >>> round(Decimal('3.75'), 1)
        Decimal('3.7')
        >>> round(Decimal('3.75'), -1)
        Decimal('0E+1')

### Operandos lógicos

Os métodos `logical_and()`, `logical_invert()`, `logical_or()` e `logical_xor()` esperam que seus argumentos sejam operandos lógicos. Um operando lógico é uma instância de `Decimal` cujo expoente e sinal são zero e cujos dígitos são todos `0` ou `1`.

## Objetos de contexto

Contextos são ambientes para operações aritméticas. Eles governam a precisão, estabelecem regras para arredondamento, determinam quais sinais são tratados como exceções e limitam o intervalo dos expoentes.

Cada thread possui seu próprio contexto atual que é acessado ou alterado usando as funções `getcontext()` e `setcontext()`:

decimal.getcontext()

  Retorna o contexto atual para a thread ativa.

decimal.setcontext(c)

  Define o contexto atual para a thread ativa como C.

Você também pode usar a instrução `with` e a função `localcontext()` para alterar temporariamente o contexto ativo.

decimal.localcontext(ctx=None, **kwargs)

  Retorna um gerenciador de contexto que vai definir o contexto atual da thread ativa para uma cópia de ctx na entrada da instrução “with” e restaurar o contexto anterior ao sair da instrução “with”. Se nenhum contexto for especificado, uma cópia do contexto atual será usada. O argumento kwargs é usado para definir os atributos do novo contexto.

  Por exemplo, o código a seguir define a precisão decimal atual para 42 casas, executa um cálculo e restaura automaticamente o contexto anterior:

      from decimal import localcontext

      with localcontext() as ctx:
          ctx.prec = 42   # Efetua um cálculo de alta precisão
          s = calculate_something()
      s = +s  # Arredonda o resultado final de volta para a precisão padrão

  Usando argumentos nomeados, o código seria o seguinte:

      from decimal import localcontext

      with localcontext(prec=42) as ctx:
          s = calculate_something()
      s = +s

  Levanta `TypeError` se kwargs fornecer um atributo que `Context` não oferecer suporte. Levanta `TypeError` ou `ValueError` se kwargs fornecer um valor inválido para um atributo.

  Alterado na versão 3.11: `localcontext()` agora tem suporte à configuração de atributos de contexto através do uso de argumentos nomeados.

decimal.IEEEContext(bits)

  Retorna um objeto de contexto inicializado com os valores apropriados para um dos formatos de intercâmbio IEEE. O argumento deve ser um múltiplo de 32 e menor que `IEEE_CONTEXT_MAX_BITS`.

  Adicionado na versão 3.14.

Novos contextos também podem ser criados usando o construtor `Context` descrito abaixo. Além disso, o módulo fornece três contextos pré-criados:

decimal.BasicContext

  Este é um contexto padrão definido pela Especificação Aritmética Decimal Geral. A precisão está definida como nove. O arredondamento está definido como `ROUND_HALF_UP`. Todos os sinalizadores estão limpos. Todos as armadilhas estão ativadas (tratadas como exceções), exceto por `Inexact`, `Rounded` e `Subnormal`.

  Como muitas das armadilhas estão ativadas, esse contexto é útil para depuração.

decimal.ExtendedContext

  Este é um contexto padrão definido pela Especificação Aritmética Decimal Geral. A precisão está definida como nove. O arredondamento está definido como `ROUND_HALF_EVEN`. Todos os sinalizadores estão limpos. Nenhuma armadilha está ativada (de forma que exceções não são levantadas durante os cálculos).

  Como as armadilhas estão desativadas, esse contexto é útil para aplicativos que preferem ter o valor de resultado de `NaN` ou `Infinity` em vez de levantar exceções. Isso permite que uma aplicação conclua uma execução na presença de condições que interromperiam o programa.

decimal.DefaultContext

  Este contexto é usado pelo construtor `Context` como um protótipo para novos contextos. Alterar um campo (tal como precisão) tem o efeito de alterar o padrão para novos contextos criados pelo construtor `Context`.

  Esse contexto é mais útil em ambientes multithread. A alteração de um dos campos antes do início das threads tem o efeito de definir os padrões para todo o sistema. Não é recomendável alterar os campos após o início das threads, pois exigiria sincronização de threads para evitar condições de corrida.

  Em ambientes de thread única, é preferível não usar esse contexto. Em vez disso, basta criar contextos explicitamente, conforme descrito abaixo.

  Os valores padrão são `Context.prec`=`28`, `Context.rounding`=`ROUND_HALF_EVEN` e armadilhas ativadas para `Overflow`, `InvalidOperation` e `DivisionByZero`.

Além dos três contextos fornecidos, novos contextos podem ser criados com o construtor `Context`.

class decimal.Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)

  Cria um novo contexto. Se um campo não for especificado ou for `None`, os valores padrão serão copiados de `DefaultContext`. Se o campo flags não for especificado ou for `None`, todos os sinalizadores serão limpados.

  prec

    Um inteiro no intervalo [`1`, `MAX_PREC`] que define a precisão para operações aritméticas no contexto.

  rounding

    Uma das constantes listadas na seção Modos de arredondamento.

  traps
  flags

    Listas de todos os sinais a serem configurados. Geralmente, novos contextos devem apenas definir armadilhas e deixar os sinalizadores limpos.

  Emin
  Emax

    Números inteiros que especificam os limites externos permitidos para expoentes. Emin deve estar no intervalo [`MIN_EMIN`, `0`], Emax no intervalo [`0`, `MAX_EMAX`].

  capitals

    Assume `0` ou `1` (o padrão). Se definido como `1`, os expoentes serão impressos com um `E` maiúsculo; caso contrário, um `e` minúscula é usado: `Decimal('6.02e+23')`.

  clamp

    Assume `0` (o padrão) ou `1`. Se definido como `1`, o expoente `e` de uma instância de `Decimal` representável nesse contexto é estritamente limitado ao intervalo `Emin - prec + 1 <= e <= Emax - prec + 1`. Se clamp for `0`, uma condição mais fraca será mantida: o expoente ajustado da instância de `Decimal` é no máximo `Emax`. Quando clamp é `1`, um grande número normal terá, sempre que possível, seu expoente reduzido e um número correspondente de zeros adicionado ao seu coeficiente, para ajustar as restrições do expoente; isso preserva o valor do número, mas perde informações sobre zeros à direita significativos. Por exemplo:

        >>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999')
        Decimal('1.23000E+999')

    Um valor de clamp de `1` permite compatibilidade com os formatos de intercâmbio decimal de largura fixa especificados na IEEE 754.

  A classe `Context` define vários métodos de uso geral, bem como um grande número de métodos para fazer aritmética diretamente em um determinado contexto. Além disso, para cada um dos métodos de `Decimal` descritos acima (com exceção dos métodos `adjusted()` e `as_tuple()`) existe um método correspondente em `Context`. Por exemplo, para uma instância `C` de `Context` e uma instância `x` de `Decimal`, `C.exp(x)` é equivalente a `x.exp(context=C)`. Cada método de `Context` aceita um número inteiro do Python (uma instância de `int`) em qualquer lugar em que uma instância de Decimal seja aceita.

  clear_flags()

    Redefine todos os sinalizadores para `0`.

  clear_traps()

    Redefine todas as armadilhas para `0`.

    Adicionado na versão 3.3.

  copy()

    Retorna uma duplicata do contexto.

  copy_decimal(num)

    Retorna uma cópia da instância de Decimal num.

  create_decimal(num)

    Cria uma nova instância decimal a partir de num, mas usando self como contexto. Diferentemente do construtor de `Decimal`, a precisão do contexto, o método de arredondamento, os sinalizadores e as armadilhas são aplicadas à conversão.

    Isso é útil porque as constantes geralmente são fornecidas com uma precisão maior do que a necessária pela aplicação. Outro benefício é que o arredondamento elimina imediatamente os efeitos indesejados dos dígitos além da precisão atual. No exemplo a seguir, o uso de entradas não arredondadas significa que adicionar zero a uma soma pode alterar o resultado:

        >>> getcontext().prec = 3
        >>> Decimal('3.4445') + Decimal('1.0023')
        Decimal('4.45')
        >>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023')
        Decimal('4.44')

    Este método implementa a operação “to-number” da especificação IBM. Se o argumento for uma string, nenhum espaço em branco à esquerda ou à direita ou sublinhado serão permitidos.

  create_decimal_from_float(f)

    Cria uma nova instância de Decimal a partir de um ponto flutuante f, mas arredondando usando self como contexto. Diferentemente do método da classe `Decimal.from_float()`, a precisão do contexto, o método de arredondamento, os sinalizadores e as armadilhas são aplicados à conversão.

        >>> context = Context(prec=5, rounding=ROUND_DOWN)
        >>> context.create_decimal_from_float(math.pi)
        Decimal('3.1415')
        >>> context = Context(prec=5, traps=[Inexact])
        >>> context.create_decimal_from_float(math.pi)
        Traceback (most recent call last):
            ...
        decimal.Inexact: None

    Adicionado na versão 3.1.

  Etiny()

    Retorna um valor igual a `Emin - prec + 1`, que é o valor mínimo do expoente para resultados subnormais. Quando ocorre o estouro negativo, o expoente é definido como `Etiny`.

  Etop()

    Retorna um valor igual a `Emax - prec + 1`.

  A abordagem usual para trabalhar com decimais é criar instâncias de `Decimal` e depois aplicar operações aritméticas que ocorrem no contexto atual da thread ativa. Uma abordagem alternativa é usar métodos de contexto para calcular dentro de um contexto específico. Os métodos são semelhantes aos da classe `Decimal` e são contados apenas brevemente aqui.

  abs(x)

    Retorna o valor absoluto de x.

  add(x, y)

    Retorna a soma de x e y.

  canonical(x)

    Retorna o mesmo objeto de Decimal x.

  compare(x, y)

    Compara x e y numericamente.

  compare_signal(x, y)

    Compara os valores dos dois operandos numericamente.

  compare_total(x, y)

    Compara dois operandos usando sua representação abstrata.

  compare_total_mag(x, y)

    Compara dois operandos usando sua representação abstrata, ignorando o sinal.

  copy_abs(x)

    Retorna uma cópia de x com o sinal definido para 0.

  copy_negate(x)

    Retorna uma cópia de x com o sinal invertido.

  copy_sign(x, y)

    Copia o sinal de y para x.

  divide(x, y)

    Retorna x dividido por y.

  divide_int(x, y)

    Retorna x dividido por y, truncado para um inteiro.

  divmod(x, y)

    Divide dois números e retorna a parte inteira do resultado.

  exp(x)

    Retorna `e ** x`.

  fma(x, y, z)

    Retorna x multiplicado por y, mais z.

  is_canonical(x)

    Retorna `True` se x for canonical; caso contrário, retorna `False`.

  is_finite(x)

    Retorna `True` se x for finito; caso contrário, retorna `False`.

  is_infinite(x)

    Retorna `True` se x for infinito; caso contrário, retorna `False`.

  is_nan(x)

    Retorna `True` se x for qNaN ou sNaN; caso contrário, retorna `False`.

  is_normal(x)

    Retorna `True` se x for um número normal; caso contrário, retorna `False`.

  is_qnan(x)

    Retorna `True` se x for um NaN silencioso; caso contrário, retorna `False`.

  is_signed(x)

    Retorna `True` se x for negativo; caso contrário, retorna `False`.

  is_snan(x)

    Retorna `True` se x for um NaN sinalizador; caso contrário, retorna `False`.

  is_subnormal(x)

    Retorna `True` se x for subnormal; caso contrário, retorna `False`.

  is_zero(x)

    Retorna `True` se x for zero; caso contrário, retorna `False`.

  ln(x)

    Retorna o logaritmo natural (base e) de x.

  log10(x)

    Retorna o logaritmo de base 10 de x.

  logb(x)

    Retorna o expoente da magnitude do MSD do operando.

  logical_and(x, y)

    Aplica a operação lógica e entre cada dígito do operando.

  logical_invert(x)

    Inverte todos os dígitos em x.

  logical_or(x, y)

    Aplica a operação lógica ou entre cada dígito do operando.

  logical_xor(x, y)

    Aplica a operação lógica ou exclusivo entre cada dígito do operando.

  max(x, y)

    Compara dois valores numericamente e retorna o máximo.

  max_mag(x, y)

    Compara dois valores numericamente com seu sinal ignorado.

  min(x, y)

    Compara dois valores numericamente e retorna o mínimo.

  min_mag(x, y)

    Compara dois valores numericamente com seu sinal ignorado.

  minus(x)

    Minus corresponde ao operador de subtração de prefixo unário no Python.

  multiply(x, y)

    Retorna o produto de x e y.

  next_minus(x)

    Retorna o maior número representável menor que x.

  next_plus(x)

    Retorna o menor número representável maior que x.

  next_toward(x, y)

    Retorna o número mais próximo a x, em direção a y.

  normalize(x)

    Reduz x para sua forma mais simples.

  number_class(x)

    Retorna uma indicação da classe de x.

  plus(x)

    Plus corresponde ao operador de soma de prefixo unário no Python. Esta operação aplica a precisão e o arredondamento do contexto, portanto não é uma operação de identidade.

  power(x, y, modulo=None)

    Retorna `x` à potência de `y`, com a redução de módulo `modulo` se fornecido.

    Com dois argumentos, calcula `x**y`. Se `x` for negativo, `y` deve ser inteiro. O resultado será inexato, a menos que `y` seja inteiro e o resultado seja finito e possa ser expresso exatamente em “precisão” dígitos. O modo de arredondamento do contexto é usado. Os resultados são sempre arredondados corretamente na versão Python.

    `Decimal(0) ** Decimal(0)` resulta em `InvalidOperation`, e se `InvalidOperation` não for capturado, resulta em `Decimal('NaN')`.

    Alterado na versão 3.3: O módulo C calcula `power()` em termos das funções corretamente arredondadas `exp()` e `ln()`. O resultado é bem definido, mas apenas “quase sempre corretamente arredondado”.

    Com três argumentos, calcula `(x**y) % modulo`. Para o formulário de três argumentos, as seguintes restrições nos argumentos são válidas:

    - todos os três argumentos devem ser inteiros

    - `y` não pode ser negativo

    - pelo menos um de `x` ou `y` não pode ser negativo

    - `modulo` não pode ser zero e deve ter pelo menos “precisão” dígitos

    O valor resultante de `Context.power(x, y, modulo)` é igual ao valor que seria obtido ao computar `(x**y) % modulo` com precisão ilimitada, mas é calculado com mais eficiência . O expoente do resultado é zero, independentemente dos expoentes de `x`, `y` e `modulo`. O resultado é sempre exato.

  quantize(x, y)

    Retorna um valor igual a x (arredondado), com o expoente de y.

  radix()

    Só retorna 10, já que isso é Decimal, :)

  remainder(x, y)

    Retorna o resto da divisão inteira.

    O sinal do resultado, se diferente de zero, é o mesmo que o do dividendo original.

  remainder_near(x, y)

    Retorna `x - y * n`, onde n é o número inteiro mais próximo do valor exato de `x / y` (se o resultado for 0, seu sinal será o sinal de x).

  rotate(x, y)

    Retorna uma cópia re de x, y vezes.

  same_quantum(x, y)

    Retorna `True` se os dois operandos tiverem o mesmo expoente.

  scaleb(x, y)

    Retorna o primeiro operando após adicionar o segundo valor seu exp.

  shift(x, y)

    Retorna uma cópia deslocada de x, y vezes.

  sqrt(x)

    Raiz quadrada de um número não negativo para precisão do contexto.

  subtract(x, y)

    Retorna a diferença entre x e y.

  to_eng_string(x)

    Converte em uma string, usando notação de engenharia, se for necessário um expoente.

    A notação de engenharia possui um expoente que é múltiplo de 3. Isso pode deixar até 3 dígitos à esquerda da casa decimal e pode exigir a adição de um ou dois zeros à direita.

  to_integral_exact(x)

    Arredonda para um número inteiro.

  to_sci_string(x)

    Converte um número em uma string usando notação científica.

## Constantes

As constantes nesta seção são relevantes apenas para o módulo C. Eles também estão incluídos na versão pura do Python para compatibilidade.

| 32 bits | 64 bits
--- | --- | ---

decimal.MAX_PREC

`425000000`

`999999999999999999`

decimal.MAX_EMAX

`425000000`

`999999999999999999`

decimal.MIN_EMIN

`-425000000`

`-999999999999999999`

decimal.MIN_ETINY

`-849999999`

`-1999999999999999997`

decimal.IEEE_CONTEXT_MAX_BITS

`256`

`512`

decimal.HAVE_THREADS

  O valor é `True`. Descontinuado porque o Python agora sempre tem threads.

  Descontinuado desde a versão 3.9.

decimal.HAVE_CONTEXTVAR

  O valor padrão é `True`. Se o Python for `configurado usando a opção --without-decimal-contextvar`, a versão C usará um contexto local de thread em vez de local de corrotina e o valor será `False`. Isso é um pouco mais rápido em alguns cenários de contexto aninhados.

  Adicionado na versão 3.8.3.

## Modos de arredondamento

decimal.ROUND_CEILING

  Arredonda para `Infinity`.

decimal.ROUND_DOWN

  Arredonda para zero.

decimal.ROUND_FLOOR

  Arredonda para `-Infinity`.

decimal.ROUND_HALF_DOWN

  Arrendonda para o mais próximo com empates tendendo a zero.

decimal.ROUND_HALF_EVEN

  Arredonda para o mais próximo com empates indo para o mais próximo inteiro par.

decimal.ROUND_HALF_UP

  Arrendonda para o mais próximo com empates se afastando de zero.

decimal.ROUND_UP

  Arredonda se afastando de zero.

decimal.ROUND_05UP

  Arredonda se afastando de zero se o último dígito após o arredondamento para zero fosse 0 ou 5; caso contrário, arredonda para zero.

## Sinais

Sinais representam condições que surgem durante o cálculo. Cada um corresponde a um sinalizador de contexto e um ativador de armadilha de contexto.

O sinalizador de contexto é definido sempre que a condição é encontrada. Após o cálculo, os sinalizadores podem ser verificados para fins informativos (por exemplo, para determinar se um cálculo era exato). Depois de verificar os sinalizadores, certifique-se de limpar todos os sinalizadores antes de iniciar o próximo cálculo.

Se o ativador de armadilha de contexto estiver definido para o sinal, a condição fará com que uma exceção Python seja levantada. Por exemplo, se a armadilha `DivisionByZero` for configurada, uma exceção `DivisionByZero` será levantada ao encontrar a condição.

class decimal.Clamped

  Altera um expoente para ajustar as restrições de representação.

  Normalmente, clamping ocorre quando um expoente fica fora dos limites do contexto `Emin` e `Emax`. Se possível, o expoente é reduzido para caber adicionando zeros ao coeficiente.

class decimal.DecimalException

  Classe base para outros sinais e uma subclasse de `ArithmeticError`.

class decimal.DivisionByZero

  Sinaliza a divisão de um número não infinito por zero.

  Pode ocorrer com divisão, divisão de módulo ou ao elevar um número a uma potência negativa. Se este sinal não for capturado, retornará `Infinity` ou `-Infinity` com o sinal determinado pelas entradas do cálculo.

class decimal.Inexact

  Indica que o arredondamento ocorreu e o resultado não é exato.

  Sinaliza quando dígitos diferentes de zero foram descartados durante o arredondamento. O resultado arredondado é retornado. O sinalizador ou armadilha de sinal é usado para detectar quando os resultados são inexatos.

class decimal.InvalidOperation

  Uma operação inválida foi realizada.

  Indica que uma operação foi solicitada que não faz sentido. Se não for capturado, retorna `NaN`. As possíveis causas incluem:

      Infinity - Infinity
      0 * Infinity
      Infinity / Infinity
      x % 0
      Infinity % x
      sqrt(-x) and x > 0
      0 ** 0
      x ** (non-integer)
      x ** Infinity

class decimal.Overflow

  Estouro numérico.

  Indica que o expoente é maior que `Context.Emax` após o arredondamento ocorrer. Se não for capturado, o resultado depende do modo de arredondamento, puxando para dentro para o maior número finito representável ou arredondando para fora para `Infinity`. Nos dois casos, `Inexact` e `Rounded` também são sinalizados.

class decimal.Rounded

  O arredondamento ocorreu, embora possivelmente nenhuma informação tenha sido perdida.

  Sinalizado sempre que o arredondamento descarta dígitos; mesmo que esses dígitos sejam zero (como arredondamento `5.00` a `5.0`). Se não for capturado, retorna o resultado inalterado. Este sinal é usado para detectar a perda de dígitos significativos.

class decimal.Subnormal

  O expoente foi menor que `Emin` antes do arredondamento.

  Ocorre quando um resultado da operação é subnormal (o expoente é muito pequeno). Se não for capturado, retorna o resultado inalterado.

class decimal.Underflow

  Estouro negativo numérico com resultado arredondado para zero.

  Ocorre quando um resultado subnormal é empurrado para zero arredondando. `Inexact` e `Subnormal` também são sinalizados.

class decimal.FloatOperation

  Ativa semânticas mais rigorosas para misturar objetos de float com de Decimal.

  Se o sinal não for capturado (padrão), a mistura de tipos float e Decimal será permitida no construtor `Decimal`, `create_decimal()` e em todos os operadores de comparação. Tanto a conversão quanto as comparações são exatas. Qualquer ocorrência de uma operação mista é registrada silenciosamente pela configuração `FloatOperation` nos sinalizadores de contexto. Conversões explícitas com `from_float()` ou `create_decimal_from_float()` não definem o sinalizador.

  Caso contrário (o sinal é capturado), apenas comparações de igualdade e conversões explícitas são silenciosas. Todas as outras operações mistas levantam `FloatOperation`.

A tabela a seguir resume a hierarquia de sinais:

    exceptions.ArithmeticError(exceptions.Exception)
        DecimalException
            Clamped
            DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
            Inexact
                Overflow(Inexact, Rounded)
                Underflow(Inexact, Rounded, Subnormal)
            InvalidOperation
            Rounded
            Subnormal
            FloatOperation(DecimalException, exceptions.TypeError)

## Observações sobre ponto flutuante

### Atenuando o erro de arredondamento com maior precisão

O uso do ponto flutuante decimal elimina o erro de representação decimal (possibilitando representar `0.1` de forma exata); no entanto, algumas operações ainda podem sofrer erros de arredondamento quando dígitos diferentes de zero excederem a precisão fixa.

Os efeitos do erro de arredondamento podem ser amplificados pela adição ou subtração de quantidades quase compensadoras, resultando em perda de significância. Knuth fornece dois exemplos instrutivos em que a aritmética de ponto flutuante arredondado com precisão insuficiente causa a quebra das propriedades associativas e distributivas da adição:

    # exemplos de Seminumerical Algorithms, Section 4.2.2.
    >>> from decimal import Decimal, getcontext
    >>> getcontext().prec = 8

    >>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
    >>> (u + v) + w
    Decimal('9.5111111')
    >>> u + (v + w)
    Decimal('10')

    >>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
    >>> (u*v) + (u*w)
    Decimal('0.01')
    >>> u * (v+w)
    Decimal('0.0060000')

O módulo `decimal` permite restaurar as identidades expandindo a precisão o suficiente para evitar perda de significância:

    >>> getcontext().prec = 20
    >>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
    >>> (u + v) + w
    Decimal('9.51111111')
    >>> u + (v + w)
    Decimal('9.51111111')
    >>>
    >>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
    >>> (u*v) + (u*w)
    Decimal('0.0060000')
    >>> u * (v+w)
    Decimal('0.0060000')

### Valores especiais

O sistema numérico para o módulo `decimal` fornece valores especiais, incluindo `NaN`, `sNaN`, `-Infinity`, `Infinity`, e dois zeros, `+0` e `-0`.

Os infinitos podem ser construídos diretamente com: `Decimal('Infinity')`. Além disso, eles podem resultar da divisão por zero quando o sinal `DivisionByZero` não é capturado. Da mesma forma, quando o sinal `Overflow` não é capturado, o infinito pode resultar do arredondamento além dos limites do maior número representável.

Os infinitos contêm sinais (afins) e podem ser usados em operações aritméticas, onde são tratados como números muito grandes e indeterminados. Por exemplo, adicionar uma constante ao infinito fornece outro resultado infinito.

Algumas operações são indeterminadas e retornam `NaN` ou, se o sinal `InvalidOperation` for capturado, levanta uma exceção. Por exemplo, `0/0` retorna `NaN`, que significa “não é um número” em inglês. Esta variação de `NaN` é silenciosa e, uma vez criada, fluirá através de outros cálculos sempre resultando em outra `NaN`. Esse comportamento pode ser útil para uma série de cálculos que ocasionalmente têm entradas ausentes — ele permite que o cálculo continue enquanto sinaliza resultados específicos como inválidos.

Uma variante é `sNaN`, que sinaliza em vez de permanecer em silêncio após cada operação. Esse é um valor de retorno útil quando um resultado inválido precisa interromper um cálculo para tratamento especial.

O comportamento dos operadores de comparação do Python pode ser um pouco surpreendente onde um `NaN` está envolvido. Um teste de igualdade em que um dos operandos é um `NaN` silencioso ou sinalizador sempre retorna `False` (mesmo ao fazer `Decimal('NaN')==Decimal('NaN')`), enquanto um teste de desigualdade sempre retorna `True`. Uma tentativa de comparar dois decimais usando qualquer um dos operadores `<`, `<=`, `>` ou `>=` levantará o sinal `InvalidOperation` se um dos operandos for um `NaN` e retorna `False` se esse sinal não for capturado. Observe que a especificação aritmética decimal geral não especifica o comportamento das comparações diretas; estas regras para comparações envolvendo a `NaN` foram retiradas do padrão IEEE 854 (consulte a Tabela 3 na seção 5.7). Para garantir uma rígida conformidade com os padrões, use os métodos `compare()` e `compare_signal()`.

Os zeros com sinais podem resultar de cálculos insuficientes. Eles mantêm o sinal que teria resultado se o cálculo tivesse sido realizado com maior precisão. Como sua magnitude é zero, os zeros positivos e negativos são tratados como iguais e seu sinal é informacional.

Além dos dois zeros com sinais que são distintos e iguais, existem várias representações de zero com diferentes precisões e ainda com valor equivalente. Isso leva um pouco de tempo para se acostumar. Para um olho acostumado a representações de ponto flutuante normalizadas, não é imediatamente óbvio que o seguinte cálculo retorne um valor igual a zero:

    >>> 1 / Decimal('Infinity')
    Decimal('0E-1000026')

## Trabalhando com threads

A função `getcontext()` acessa um objeto `Context` diferente para cada thread. Ter contextos de threads separadas significa que as threads podem fazer alterações (como `getcontext().prec=10`) sem interferir em outras threads.

Da mesma forma, a função `setcontext()` atribui automaticamente seu alvo à thread atual.

Se `setcontext()` não tiver sido chamado antes de `getcontext()`, então `getcontext()` criará automaticamente um novo contexto para uso na thread atual. Novos objetos de contexto têm valores padrão definidos a partir do objeto `decimal.DefaultContext`.

O sinalizador `sys.flags.thread_inherit_context` afeta o contexto de novas threads. Se o sinalizador for falso, as novas threads começarão com um contexto vazio. Nesse caso, `getcontext()` criará um novo objeto de contexto quando chamado e usará os valores padrão de DefaultContext. Se o sinalizador for verdadeiro, as novas threads começarão com uma cópia do contexto do chamador de `threading.Thread.start()`.

Para controlar os padrões para que cada thread, use os mesmos valores em todo a aplicação, modifique diretamente o objeto DefaultContext. Isso deve ser feito antes de qualquer thread ser iniciada, para que não haja uma condição de corrida entre as threads chamando `getcontext()`. Por exemplo:

    # Define padrões para todo a aplicação para todas as threads prestes a serem iniciadas
    DefaultContext.prec = 12
    DefaultContext.rounding = ROUND_DOWN
    DefaultContext.traps = ExtendedContext.traps.copy()
    DefaultContext.traps[InvalidOperation] = 1
    setcontext(DefaultContext)

    # Depois, as threads podem ser iniciadas
    t1.start()
    t2.start()
    t3.start()
     . . .

## Receitas

Aqui estão algumas receitas que servem como funções utilitárias e que demonstram maneiras de trabalhar com a classe `Decimal`:

    def moneyfmt(value, places=2, curr='', sep=',', dp='.',
                 pos='', neg='-', trailneg=''):
        """Converte Decimal para uma string formatada de moead.

        places:  número obrigatório de casas após o ponto decimal
        curr:    símbolo de moeda opcional antes do sinal (pode estar em branco)
        sep:     separador de agrupamento opcional (vírgula, ponto, espaço ou espaço em branco)
        dp:      indicador de ponto decimal (vírgula ou ponto)
                 especificar como espaço em branco somente quando places for zero
        pos:     sinal opcional para números positivos: '+', espaço ou espaço em branco
        neg:     sinal opcional para números negativos: '-', '(', espaço ou espaço em branco
        trailneg:indicador de menos final opcional: '-', ')', espaço ou espaço em branco

        >>> d = Decimal('-1234567.8901')
        >>> moneyfmt(d, curr='$')
        '-$1,234,567.89'
        >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
        '1.234.568-'
        >>> moneyfmt(d, curr='$', neg='(', trailneg=')')
        '($1,234,567.89)'
        >>> moneyfmt(Decimal(123456789), sep=' ')
        '123 456 789.00'
        >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
        '<0.02>'

        """
        q = Decimal(10) ** -places      # 2 casas --> '0.01'
        sign, digits, exp = value.quantize(q).as_tuple()
        result = []
        digits = list(map(str, digits))
        build, next = result.append, digits.pop
        if sign:
            build(trailneg)
        for i in range(places):
            build(next() if digits else '0')
        if places:
            build(dp)
        if not digits:
            build('0')
        i = 0
        while digits:
            build(next())
            i += 1
            if i == 3 and digits:
                i = 0
                build(sep)
        build(curr)
        build(neg if sign else pos)
        return ''.join(reversed(result))

    def pi():
        """Compute Pi to the current precision.

        >>> print(pi())
        3.141592653589793238462643383

        """
        getcontext().prec += 2  # dígitos extras para casas intermediárias
        three = Decimal(3)      # substitui "three=3.0" para pontos flutuantes regulares
        lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
        while s != lasts:
            lasts = s
            n, na = n+na, na+8
            d, da = d+da, da+32
            t = (t * n) / d
            s += t
        getcontext().prec -= 2
        return +s               # unário com mais aplica a nova precisão

    def exp(x):
        """Retorna e elevado à potência de x. O tipo de resultado corresponde ao tipo de entrada.

        >>> print(exp(Decimal(1)))
        2.718281828459045235360287471
        >>> print(exp(Decimal(2)))
        7.389056098930650227230427461
        >>> print(exp(2.0))
        7.38905609893
        >>> print(exp(2+0j))
        (7.38905609893+0j)

        """
        getcontext().prec += 2
        i, lasts, s, fact, num = 0, 0, 1, 1, 1
        while s != lasts:
            lasts = s
            i += 1
            fact *= i
            num *= x
            s += num / fact
        getcontext().prec -= 2
        return +s

    def cos(x):
        """Retorna o cosseno de x medido em radianos.

        A aproximação da série de Taylor funciona melhor para um valor pequeno de x.
        Para valores maiores, primeiro calcule x = x % (2 * pi).

        >>> print(cos(Decimal('0.5')))
        0.8775825618903727161162815826
        >>> print(cos(0.5))
        0.87758256189
        >>> print(cos(0.5+0j))
        (0.87758256189+0j)

        """
        getcontext().prec += 2
        i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 1
        while s != lasts:
            lasts = s
            i += 2
            fact *= i * (i-1)
            num *= x * x
            sign *= -1
            s += num / fact * sign
        getcontext().prec -= 2
        return +s

    def sin(x):
        """Retorna o seno de x medido em radianos.

        A aproximação da série de Taylor funciona melhor para um valor pequeno de x.
        Para valores maiores, primeiro calcule x = x % (2 * pi).

        >>> print(sin(Decimal('0.5')))
        0.4794255386042030002732879352
        >>> print(sin(0.5))
        0.479425538604
        >>> print(sin(0.5+0j))
        (0.479425538604+0j)

        """
        getcontext().prec += 2
        i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 1
        while s != lasts:
            lasts = s
            i += 2
            fact *= i * (i-1)
            num *= x * x
            sign *= -1
            s += num / fact * sign
        getcontext().prec -= 2
        return +s

## FAQ sobre Decimal

P. É complicado digitar `decimal.Decimal('1234.5')`. Existe uma maneira de minimizar a digitação ao usar o interpretador interativo?

R. Alguns usuários abreviam o construtor para apenas uma única letra:

    >>> D = decimal.Decimal
    >>> D('1.23') + D('3.45')
    Decimal('4.68')

P. Em uma aplicação de ponto fixo com duas casas decimais, algumas entradas têm muitas casas e precisam ser arredondadas. Outros não devem ter dígitos em excesso e precisam ser validados. Quais métodos devem ser usados?

R. O método `quantize()` arredonda para um número fixo de casas decimais. Se a armadilha `Inexact` estiver configurada, também será útil para validação:

    >>> TWOPLACES = Decimal(10) ** -2       # same as Decimal('0.01')

    >>> # Round to two places
    >>> Decimal('3.214').quantize(TWOPLACES)
    Decimal('3.21')

    >>> # Validate that a number does not exceed two places
    >>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
    Decimal('3.21')

    >>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
    Traceback (most recent call last):
       ...
    Inexact: None

P. Assim que eu tiver entradas de duas casas válidas, como mantenho essa invariante em uma aplicação?

R. Algumas operações como adição, subtração e multiplicação por um número inteiro preservam automaticamente o ponto fixo. Outras operações, como divisão e multiplicação não inteira, alteram o número de casas decimais e precisam ser seguidas com uma etapa `quantize()`:

    >>> a = Decimal('102.72')           # Initial fixed-point values
    >>> b = Decimal('3.17')
    >>> a + b                           # Addition preserves fixed-point
    Decimal('105.89')
    >>> a - b
    Decimal('99.55')
    >>> a * 42                          # So does integer multiplication
    Decimal('4314.24')
    >>> (a * b).quantize(TWOPLACES)     # Must quantize non-integer multiplication
    Decimal('325.62')
    >>> (b / a).quantize(TWOPLACES)     # And quantize division
    Decimal('0.03')

No desenvolvimento de aplicações de ponto fixo, é conveniente definir funções para manipular a etapa `quantize()`:

    >>> def mul(x, y, fp=TWOPLACES):
    ...     return (x * y).quantize(fp)
    ...
    >>> def div(x, y, fp=TWOPLACES):
    ...     return (x / y).quantize(fp)

    >>> mul(a, b)                       # Automatically preserve fixed-point
    Decimal('325.62')
    >>> div(b, a)
    Decimal('0.03')

P. Existem várias maneiras de expressar o mesmo valor. Os números `200`, `200.000`, `2E2` e `.02E+4` têm todos o mesmo valor em várias precisões. Existe uma maneira de transformá-los em um único valor canônico reconhecível?

R. O método `normalize()` mapeia todos os valores equivalentes para um único representativo:

    >>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
    >>> [v.normalize() for v in values]
    [Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]

P. Quando ocorre o arredondamento em um cálculo?

R. Ocorre após o cálculo. A filosofia da especificação decimal é que os números são considerados exatos e criados independentemente do contexto atual. Eles podem até ter maior precisão do que o contexto atual. O processo de cálculo com essas entradas exatas e, em seguida, o arredondamento (ou outras operações de contexto) é aplicado ao resultado do cálculo:

    >>> getcontext().prec = 5
    >>> pi = Decimal('3.1415926535')   # Mais de 5 dígitos
    >>> pi                             # Todos os dígitos são retidos
    Decimal('3.1415926535')
    >>> pi + 0                         # Arredondado após uma adição
    Decimal('3.1416')
    >>> pi - Decimal('0.00005')        # Subtrai números não arredondados e depois arredonda
    Decimal('3.1415')
    >>> pi + 0 - Decimal('0.00005').   # Os valores intermediários são arredondados
    Decimal('3.1416')

P. Alguns valores decimais sempre são exibidas com notação exponencial. Existe uma maneira de obter uma representação não exponencial?

R. Para alguns valores, a notação exponencial é a única maneira de expressar o número de casas significativas no coeficiente. Por exemplo, expressar `5.0E+3` como `5000` mantém o valor constante, mas não pode mostrar a significância de duas casa do original.

Se uma aplicação não se importa com o rastreamento da significância, é fácil remover o expoente e os zeros à direita, perdendo a significância, mas mantendo o valor inalterado:

    >>> def remove_exponent(d):
    ...     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

    >>> remove_exponent(Decimal('5E+3'))
    Decimal('5000')

P. Existe uma maneira de converter um float comum em um `Decimal`?

R. Sim, qualquer número de ponto flutuante binário pode ser expresso exatamente como um Decimal, embora uma conversão exata possa exigir mais precisão do que a intuição sugere:

    >>> Decimal(math.pi)
    Decimal('3.141592653589793115997963468544185161590576171875')

P. Em um cálculo complexo, como posso ter certeza de que não obtive um resultado falso devido à precisão insuficiente ou a anomalias de arredondamento.

R. O módulo decimal facilita o teste de resultados. Uma prática recomendada é executar novamente os cálculos usando maior precisão e com vários modos de arredondamento. Resultados amplamente diferentes indicam precisão insuficiente, problemas no modo de arredondamento, entradas mal condicionadas ou um algoritmo numericamente instável.

P. Notei que a precisão do contexto é aplicada aos resultados das operações, mas não às entradas. Há algo a observar ao misturar valores de diferentes precisões?

R. Sim. O princípio é que todos os valores são considerados exatos, assim como a aritmética desses valores. Somente os resultados são arredondados. A vantagem das entradas é que “o que você vê é o que você obtém”. Uma desvantagem é que os resultados podem parecer estranhos se você esquecer que as entradas não foram arredondadas:

    >>> getcontext().prec = 3
    >>> Decimal('3.104') + Decimal('2.104')
    Decimal('5.21')
    >>> Decimal('3.104') + Decimal('0.000') + Decimal('2.104')
    Decimal('5.20')

A solução é aumentar a precisão ou forçar o arredondamento das entradas usando a operação unária de mais:

    >>> getcontext().prec = 3
    >>> +Decimal('1.23456789')      # unary plus triggers rounding
    Decimal('1.23')

Como alternativa, as entradas podem ser arredondadas na criação usando o método `Context.create_decimal()`:

    >>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
    Decimal('1.2345')

P. A implementação do CPython é rápida para números grandes?

A. Sim. Nas implementações CPython e PyPy3, as versões C/CFFI do módulo decimal integram a biblioteca de alta velocidade libmpdec para precisão arbitrária de aritmética de ponto flutuante decimal corretamente arredondado [1]. `libmpdec` usa a multiplicação de Karatsuba para números com tamanho médio e a Transformada Numérica de Fourier para números muito grandes.

O contexto deve ser adaptado para uma aritmética exata de precisão arbitrária. `Emin` e `Emax` devem sempre ser configurados com os valores máximos, `clamp` deve sempre ser 0 (o padrão). A configuração de `prec` requer alguns cuidados.

A abordagem mais fácil para testar a aritmética do bignum é usar o valor máximo para `prec` também [2]:

    >>> setcontext(Context(prec=MAX_PREC, Emax=MAX_EMAX, Emin=MIN_EMIN))
    >>> x = Decimal(2) ** 256
    >>> x / 128
    Decimal('904625697166532776746648320380374280103671755200316906558262375061821325312')

Para resultados inexatos, `MAX_PREC` é muito grande em plataformas de 64 bits e a memória disponível será insuficiente:

    >>> Decimal(1) / 3
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    MemoryError

Em sistemas com alocação excessiva (por exemplo, Linux), uma abordagem mais sofisticada é ajustar `prec` à quantidade de RAM disponível. Suponha que você tenha 8 GB de RAM e espere 10 operandos simultâneos usando no máximo 500 MB cada:

    >>> import sys
    >>>
    >>> # Número máximo de dígitos para um único operando usando 500 MB
    >>> # em palavras de 8 bytes com 19 dígitos por palavra (4 bytes e 9 dígitos
    >>> # para a construção de 32 bits):
    >>> maxdigits = 19 * ((500 * 1024**2) // 8)
    >>>
    >>> # Confere que isso funciona:
    >>> c = Context(prec=maxdigits, Emax=MAX_EMAX, Emin=MIN_EMIN)
    >>> c.traps[Inexact] = True
    >>> setcontext(c)
    >>>
    >>> # Preenche a precisão disponível com noves:
    >>> x = Decimal(0).logical_invert() * 9
    >>> sys.getsizeof(x)
    524288112
    >>> x + 2
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      decimal.Inexact: [<class 'decimal.Inexact'>]

Em geral (e especialmente em sistemas sem alocação excessiva), recomenda-se estimar limites ainda mais apertados e definir a armadilha `Inexact` se for esperado que todos os cálculos sejam mais precisos.

[ 1 ]

Adicionado na versão 3.3.

[ 2 ]

Alterado na versão 3.9: Esta abordagem agora funciona para todos os resultados exatos, exceto para potências de números que não sejam inteiros.