Módulo Decimal - Python
Ao trabalhar com números de ponto flutuante (float), frequentemente enfrentamos o problema de obter resultados ligeiramente imprecisos em operações:
number = 0.1 + 0.1 + 0.1
print(number) # 0.30000000000000004
Para resolver isso, uma alternativa é usar a função round()
decimal
O principal componente para lidar com números no módulo decimal
Decimal
from decimal import Decimal
number = Decimal("0.1")
Após isso, o objeto Decimal
from decimal import Decimal
number = Decimal("0.1")
number = number + number + number
print(number) # 0.3
Em operações com Decimal
number = Decimal("0.1")
number = number + 2
No entanto, não é permitido misturar números decimais float
Decimal
number = Decimal("0.1")
number = number + 0.1 # isso levanta uma exceção
Usando casas decimais adicionais, é possível definir o número de dígitos na parte decimal
number = Decimal("0.10")
number = 3 * number
print(number) # 0.30
A string "0.10" especifica duas casas decimais, mesmo que os últimos dígitos representem zeros. Assim, "0.100" indica três casas decimais.
Arredondamento de Números
Objetos Decimal
quantize()
Decimal
from decimal import Decimal
number = Decimal("0.444")
number = number.quantize(Decimal("1.00"))
print(number) # 0.44
number = Decimal("0.555678")
print(number.quantize(Decimal("1.00"))) # 0.56
number = Decimal("0.999")
print(number.quantize(Decimal("1.00"))) # 1.00
A string "1.00" indica que o arredondamento ocorrerá até duas casas decimais.
Por padrão, o arredondamento é feito usando a constante ROUND_HALF_EVEN
from decimal import Decimal, ROUND_HALF_EVEN
number = Decimal("10.025") # 2 é o par mais próximo
print(number.quantize(Decimal("1.00"), ROUND_HALF_EVEN)) # 10.02
number = Decimal("10.035") # 4 é o par mais próximo
print(number.quantize(Decimal("1.00"), ROUND_HALF_EVEN)) # 10.04
A estratégia de arredondamento é passada como segundo parâmetro no quantize
No primeiro caso, com "10.025"
"10.035"
Esse comportamento pode não ser desejável para todos, e é possível substituí-lo usando uma das seguintes constantes:
: arredonda para cima se o próximo dígito for 5 ou maior.ROUND_HALF_UP
: arredonda para cima se o próximo dígito for maior que 5.ROUND_HALF_DOWN
number = Decimal("10.026") print(number.quantize(Decimal("1.00"), ROUND_HALF_DOWN)) # 10.03 number = Decimal("10.025") print(number.quantize(Decimal("1.00"), ROUND_HALF_DOWN)) # 10.02
: arredonda para cima se o próximo dígito for 5 ou maior, mesmo se o dígito atual for zero.ROUND_05UP
number = Decimal("10.005") print(number.quantize(Decimal("1.00"), ROUND_05UP)) # 10.01 number = Decimal("10.025") print(number.quantize(Decimal("1.00"), ROUND_05UP)) # 10.02
: arredonda sempre para cima, independente do próximo dígito.ROUND_CEILING
number = Decimal("10.021") print(number.quantize(Decimal("1.00"), ROUND_CEILING)) # 10.03 number = Decimal("10.025") print(number.quantize(Decimal("1.00"), ROUND_CEILING)) # 10.03
: arredonda sempre para baixo, independente do próximo dígito.ROUND_FLOOR
number = Decimal("10.021") print(number.quantize(Decimal("1.00"), ROUND_FLOOR)) # 10.02 number = Decimal("10.025") print(number.quantize(Decimal("1.00"), ROUND_FLOOR)) # 10.02