Operação Com Número Decimal - Operações com Números Decimais | PDF | Decimal | Conceitos matemáticos
Operações com Números Decimais | PDF | Decimal | Conceitos matemáticos

Calculando com decimais: o que ninguém te conta

Operação com número decimal é basicamente multiplicar, dividir, somar ou subtrair valores que têm vírgula. A parte chata vem quando você precisa lidar com precisão, arredondamento e aqueles erros de ponto flutuante que aparecem do nada. A regra prática mais importante é: se for calcular dinheiro, esquece ponto flutuante. Usa Decimal do módulo decimal. Funciona assim:

from decimal import Decimal, ROUND_HALF_UP a = Decimal("19.99")

b = Decimal("3.50") total = (a + b).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

O resultado é 23.49, sem surpresas. Se você fizer isso com floats normais, o Python pode te devolver 23.489999999999998 e aí começa o sofrimento.

Por que 0.1 + 0.2 não dá 0.3

Isso é o problema mais clássico. O número 0.1 não existe como fração binária exata, igual a 1/3 não existe em decimal. Então o computador aproxima. A conta vira algo como 0.30000000000000004. Eu já perdi duas horas rastreando um bug assim num sistema de relatórios financeiros. O "erro" vinha de uma soma acumulada de 14 mil linhas. Nada aparecia nas provas unitárias porque cada teste usava valores redondos. A solução que eu uso hoje é simples: converter tudo para Decimal antes de qualquer operação. E sempre passar o valor como string, nunca como float. Decimal(0.1) herda o erro do float. Decimal("0.1") não herda nada.

Divisão com precisão controlada

Quando você divide dois Decimais, o Python não arredonda sozinho. Se o resultado tiver muitas casas decimais, ele pode até levantar InvalidOperation. Você precisa definir o contexto ou usar quantize explicitamente: from decimal import getcontext

getcontext().prec = 28 resultado = Decimal("10") / Decimal("3")

Isso te dá 3.333333333333333333333333333, com 28 dígitos significativos. O padrão do Python é 28, então normalmente você não precisa ajustar. Mas em bancos de dados ou APIs legadas, às vezes o contexto vem cortado pra 9 dígitos e você se surpreende com perdas de precisão sem aviso.

Arredondamento: o campo minado

Arredondar parece fácil até você precisar atender a uma norma fiscal. O Python usa banker's rounding por padrão: 2.5 vira 2, 3.5 vira 4. Em contabilidade brasileira isso pode ser problema porque algumas situações exigem ROUND_HALF_UP, que arredonda 2.5 para 3 sempre. Se você estiver gerando NF-e ou calculando ISS, confirma qual regra a legislação pede. O erro aqui não é técnico, é jurídico. Outro detalhe: arredondar no meio do cálculo muda o resultado final. Se tiver que somar três itens e depois aplicar imposto, arredonda depois da soma, não depois de cada item. A diferença costuma ser de centavos, mas em volume alto vira dinheiro real.

👉 Clique no botão abaixo para saber mais sobre o assunto!

Input do usuário: o caos invisível

Eu já vi formulário aceitar "1.500,00" no padrão americano e converter pra Decimal direto. A vírgula vira parte do número e o valor entra errado. A solução é normalizar: remover pontos de milhar, trocar vírgula por ponto, ou pedir o valor já em formato limpo. Se o usuário puder digitar anything, valida antes de converter. Uma validação rápida que funciona:

import re pattern = re.compile(r'^\d{1,12}([.,]\d{1,2})?$')

if not pattern.match(valor): raise ValueError("formato inválido") valor = valor.replace(".", "").replace(",", ".")

Isso aceita até 12 dígitos antes da casa decimal e no máximo 2 após. O limite de 12 dígitos é arbitrário, ajuste conforme sua necessidade. Em preços de produto costuma sobrar, em folha de pagamento às vezes não.

Pilhas que usam float e você nem percebe

Numpy, pandas, bibliotecas gráficas — todos trabalham com float por padrão. Se você passa Decimal pra uma função do pandas, ela converte de volta pra float. Eu aprendi isso na marra quando um gráfico de custos ficou com barras levemente deslocadas. A diferença era de 0.0000001, mas visualmente destoava. Se precisar manter precisão em todo o pipeline, fique dentro do mundo Decimal desde a entrada até a saída. Ou aceite o float e arredonde só na apresentação final, mas nunca confie no valor armazenado para comparações de igualdade.

Comparação: nunca use ==

Isso vale tanto pra float quanto pra Decimal em certos contextos. A comparação exata de decimais derivados de operações múltiplas pode falhar se uma conversão intermediária introduziu rounding. O jeito seguro é usar epsilon para float, ou garantir que ambos os valores passaram pelo mesmo caminho de arredondamento antes de comparar. abs(a - b)

Decimal("0.005")

Funciona bem pra valores monetários com duas casas decimais. A margem de 0.005 cobre o caso de arredondamento diferente entre duas rotas de cálculo.

Cenários onde Decimal não resolve

Se você precisa de velocidade bruta processando milhões de operações por segundo, Decimal é mais lento que float. A diferença é pequena em contas isoladas, mas em batches grandes vira questão de segundos versus minutos. Para ciência de dados, machine learning ou simulações numéricas, float com tolerância é a escolha certa. O problema aparece quando você trata números decimais como se fossem exatos quando na verdade são aproximações. Outro cenário: sistemas distribuídos com serialização JSON. Decimal não tem representação nativa em JSON. Se você retorna Decimal direto numa API REST, o serializer vai virar string ou dar erro. Decida early se a interface expõe Decimal como string ("19.99") ou como float com convenção de casas decimais. Documenta isso, senão todo mundo adivinha.

Resumindo, operação com número decimal no dia a dia gira em torno de três decisões: usar Decimal ao invés de float para dinheiro, controlar explicitamente o arredondamento, e validar input antes de converter. O resto é detalhe.