Resumo : neste tutorial, você aprenderá sobre o decimal
módulo Python que oferece suporte à aritmética de ponto flutuante decimal com arredondamento rápido e correto.
Introdução ao módulo decimal Python
Muitos números decimais não têm representações exatas em ponto flutuante binário , como 0,1. Ao usar esses números em operações aritméticas, você obterá um resultado inesperado. Por exemplo:
x = 0.1
y = 0.1
z = 0.1
s = x + y + z
print(s)
Linguagem de código: PHP ( php )
Saída:
0.30000000000000004
Linguagem de código: CSS ( css )
O resultado é 0,30000000000000004, não 0,3.
Para resolver este problema, você usa a Decimal
classe do decimal
módulo da seguinte forma:
import decimal
from decimal import Decimal
x = Decimal('0.1')
y = Decimal('0.1')
z = Decimal('0.1')
s = x + y + z
print(s)
Linguagem de código: JavaScript ( javascript )
Saída:
0.3
Linguagem de código: CSS ( css )
A saída é a esperada.
O módulo Python decimal
suporta aritmética que funciona da mesma forma que a aritmética que você aprende na escola.
Ao contrário de floats , Python representa números decimais exatamente. E a exatidão é transferida para a aritmética. Por exemplo, a seguinte expressão retorna exatamente 0,0:
Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Linguagem de código: JavaScript ( javascript )
Contexto decimal
Decimal sempre está associado a um contexto que controla os seguintes aspectos:
- Precisão durante uma operação aritmética
- Algoritmo de arredondamento
Por padrão, o contexto é global. O contexto global é o contexto padrão. Além disso, você pode definir um contexto temporário que terá efeito local sem afetar o contexto global.
Para obter o contexto padrão, você chama a getcontext()
função do decimal
módulo:
decimal.getcontext()
Linguagem de código: CSS ( css )
A getcontext()
função retorna o contexto padrão, que pode ser global ou local.
Para criar um novo contexto copiado de outro contexto, você usa a localcontext()
função:
decimal.localcontext(ctx=None)
O localcontext()
retorna um novo contexto copiado do contexto, ctx
se especificado.
Depois de obter o objeto de contexto, você pode acessar a precisão e o roteamento por meio da propriedade prec
and respectivamente:rounding
ctx.pre
: obtém ou define a precisão. O ctx.pre é um número inteiro cujo padrão é 28ctx.rounding
: obtém ou define o mecanismo de arredondamento. O arredondamento é uma string. O padrão é'ROUND_HALF_EVEN'
. Observe que os carros alegóricos também usam esse mecanismo de arredondamento.
Python fornece os seguintes mecanismos de arredondamento:
Arredondamento | Descrição |
---|---|
ARREDONDAR PARA CIMA | arredondar a partir de zero |
ARREDONDAR PARA BAIXO | arredondar para zero |
ROUND_CEILING | arredondado para o teto (em direção ao infinito positivo) |
ROUND_FLOOR | arredondar para o chão (em direção ao infinito negativo) |
ROUND_HALF_UP | arredondar para o mais próximo, empatar a partir de zero |
ROUND_HALF_DOWN | arredondar para o mais próximo, empatar em direção a zero |
ROUND_HALF_EVEN | arredondar para o mais próximo, empatar com o par (dígito menos significativo) |
Este exemplo ilustra como obter a precisão padrão e o arredondamento do contexto padrão:
import decimal
ctx = decimal.getcontext()
print(ctx.prec)
print(ctx.rounding)
Linguagem de código: PHP ( php )
Saída:
28
ROUND_HALF_EVEN
O exemplo a seguir mostra como o 'ROUND_HALF_EVEN'
mecanismo de arredondamento entra em vigor:
import decimal
from decimal import Decimal
x = Decimal('2.25')
y = Decimal('3.35')
print(round(x, 1))
print(round(y, 1))
Linguagem de código: JavaScript ( javascript )
Saída:
2.2
3.4
Linguagem de código: CSS ( css )
Se você alterar o arredondamento para 'ROUND_HALF_UP'
, obterá um resultado diferente:
import decimal
from decimal import Decimal
ctx = decimal.getcontext()
ctx.rounding = decimal.ROUND_HALF_UP
x = Decimal('2.25')
y = Decimal('3.35')
print(round(x, 1))
print(round(y, 1))
Linguagem de código: JavaScript ( javascript )
Saída:
2.3
3.4
Linguagem de código: CSS ( css )
O exemplo a seguir mostra como copiar o contexto padrão e alterar o arredondamento para 'ROUND_HALF_UP'
:
import decimal
from decimal import Decimal
x = Decimal('2.25')
y = Decimal('3.35')
with decimal.localcontext() as ctx:
print('Local context:')
ctx.rounding = decimal.ROUND_HALF_UP
print(round(x, 1))
print(round(y, 1))
print('Global context:')
print(round(x, 1))
print(round(y, 1))
Linguagem de código: PHP ( php )
Saída:
Local context:
2.3
3.4
Global context:
2.2
3.4
Linguagem de código: CSS ( css )
Observe que o contexto local não afeta o contexto global. Após o bloco with, o Python usa o mecanismo de arredondamento padrão.
Construtor decimal
O Decimal
construtor permite criar um novo Decimal
objeto baseado em um valor:
Decimal(value='0', context=None)
Linguagem de código: JavaScript ( javascript )
O value
argumento pode ser um número inteiro, string, tupla, float ou outro objeto Decimal. Se você não fornecer o argumento value, o padrão será '0'
.
Se o valor for uma tupla, ele deverá ter três componentes: um sinal (0 para positivo ou 1 para negativo), uma tupla de dígitos e um expoente inteiro:
(sign, (digit1,digit2, digit3,...), exponent)
Por exemplo:
3.14 = 314 x 10^-2
A tupla tem três elementos como segue:
- sinal é 0
- dígitos é (3,1,4)
- expoente é -2
Portanto, você precisará passar a seguinte tupla para o Decimal
construtor:
import decimal
from decimal import Decimal
x = Decimal((0, (3, 1, 4), -2))
print(x)
Linguagem de código: JavaScript ( javascript )
Saída:
3.14
Linguagem de código: CSS ( css )
Observe que a precisão do contexto decimal afeta apenas a operação aritmética, não o Decimal
construtor. Por exemplo:
import decimal
from decimal import Decimal
decimal.getcontext().prec = 2
pi = Decimal('3.14159')
radius = 1
print(pi)
area = pi * radius * radius
print(area)
Linguagem de código: JavaScript ( javascript )
Quando você usa um float que não possui uma representação flutuante binária exata, o Decimal
construtor não pode criar uma representação decimal precisa. Por exemplo:
import decimal
from decimal import Decimal
x = Decimal(0.1)
print(x)
Linguagem de código: JavaScript ( javascript )
Saída:
0.1000000000000000055511151231257827021181583404541015625
Linguagem de código: CSS ( css )
Na prática, você usará uma string ou tupla para construir um arquivo Decimal
.
Operações aritméticas decimais
Alguns operadores aritméticos não funcionam da mesma forma que floats ou inteiros , como div ( //
) e mod( %)
.
Para números decimais, o //
operador realiza uma divisão truncada:
x // y = trunc( x / y)
Linguagem de código: JavaScript ( javascript )
A Decimal
classe fornece algumas operações matemáticas, como sqrt
e log
. Porém, não possui todas as funções definidas no math
módulo.
Quando você usa funções do math
módulo para números decimais, o Python converterá os Decimal
objetos em carros flutuantes antes de realizar operações aritméticas. Isso resulta na perda da precisão incorporada nos objetos decimais.
Resumo
- Use o módulo Python
decimal
quando desejar oferecer suporte à aritmética de ponto flutuante decimal rapidamente arredondada corretamente. - Use a
Decimal
classe dodecimal
módulo para criar objetos Decimal a partir de strings, inteiros e tuplas. - Os
Decimal
números possuem um contexto que controla a precisão e o mecanismo de arredondamento. - A
Decimal
classe não possui todos os métodos definidos nomath
módulo. No entanto, você deve usar os métodos aritméticos do Decimal, se estiverem disponíveis.