0Pricing
Java Academy · Aula

BigDecimal para Cálculos Financeiros

Use BigDecimal para evitar erros de precisão de ponto flutuante em cálculos monetários e tributários.

BigDecimal para Cálculos Financeiros é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.

BigDecimal para cálculos financeiros

Os tipos de ponto flutuante (double, float) não conseguem representar todos os valores decimais com exatidão devido à representação binária. Para dinheiro e impostos, use BigDecimal.

O problema do ponto flutuante

O ponto flutuante binário introduz pequenos erros de arredondamento. Em aplicações financeiras, esses erros se acumulam e causam problemas reais.

double price = 0.1 + 0.2;
System.out.println(price);          // 0.30000000000000004 (WRONG!)
System.out.println(price == 0.3);   // false

// Real bug: total never equals expected
double total = 0;
for (int i = 0; i < 10; i++) total += 0.1;
System.out.println(total); // 0.9999999999999999

Criando BigDecimal com segurança

Sempre crie BigDecimal a partir de uma String, não de um double. Usar o construtor que recebe double herda a imprecisão do ponto flutuante.

import java.math.BigDecimal;

// WRONG: double constructor
BigDecimal wrong = new BigDecimal(0.1);
System.out.println(wrong); // 0.1000000000000000055511...

// CORRECT: String constructor
BigDecimal correct = new BigDecimal("0.1");
System.out.println(correct); // 0.1

// Or use valueOf (also safe)
BigDecimal safe = BigDecimal.valueOf(0.1);
System.out.println(safe); // 0.1

Aritmética básica com BigDecimal

BigDecimal usa chamadas de método para realizar operações aritméticas: add(), subtract(), multiply(), divide(). Essas chamadas retornam novas instâncias de BigDecimal (imutáveis).

import java.math.BigDecimal;

BigDecimal price = new BigDecimal("19.99");
BigDecimal tax   = new BigDecimal("0.08");
BigDecimal qty   = new BigDecimal("3");

BigDecimal subtotal = price.multiply(qty);
BigDecimal taxAmount = subtotal.multiply(tax);
BigDecimal total = subtotal.add(taxAmount);

System.out.println(subtotal);  // 59.97
System.out.println(taxAmount); // 4.7976
System.out.println(total);     // 64.7676

Modos de arredondamento

RoundingMode controla como BigDecimal arredonda. Principais modos:

  • HALF_UP — arredondamento padrão (0.5 é arredondado para cima)
  • HALF_EVEN — arredondamento bancário (0.5 é arredondado para o número par mais próximo)
  • DOWN — trunca em direção a zero
  • CEILING — arredonda em direção ao infinito positivo
import java.math.*;

BigDecimal val = new BigDecimal("2.565");

System.out.println(val.setScale(2, RoundingMode.HALF_UP));   // 2.57
System.out.println(val.setScale(2, RoundingMode.HALF_EVEN)); // 2.56 (banker's)
System.out.println(val.setScale(2, RoundingMode.DOWN));      // 2.56
System.out.println(val.setScale(2, RoundingMode.CEILING));   // 2.57

Divisão e escala

A divisão com BigDecimal exige a especificação da escala e do modo de arredondamento para evitar ArithmeticException em decimais não terminantes.

import java.math.*;

BigDecimal revenue = new BigDecimal("1000.00");
BigDecimal months  = new BigDecimal("3");

// Without scale → ArithmeticException (non-terminating decimal)
try {
    revenue.divide(months);
} catch (ArithmeticException e) {
    System.out.println("Need to specify scale!");
}

// Correct: specify scale and rounding
BigDecimal monthly = revenue.divide(months, 2, RoundingMode.HALF_UP);
System.out.println(monthly); // 333.33

Comparando BigDecimals

Use compareTo() para comparar valores, não equals(). equals() considera a escala — 2.0 e 2.00 não são iguais por equals(), mas são NOT iguais? Na verdade, são ARE iguais por compareTo().

import java.math.BigDecimal;

BigDecimal a = new BigDecimal("2.0");
BigDecimal b = new BigDecimal("2.00");

System.out.println(a.equals(b));        // false (different scale)
System.out.println(a.compareTo(b));     // 0 (same value)
System.out.println(a.compareTo(b) == 0); // true

// For sorting in collections
import java.util.*;
List<BigDecimal> prices = Arrays.asList(
    new BigDecimal("3.50"), new BigDecimal("1.00"), new BigDecimal("2.75")
);
Collections.sort(prices);
System.out.println(prices); // [1.00, 2.75, 3.50]

MathContext para algarismos significativos

MathContext especifica a precisão (algarismos significativos) e o modo de arredondamento. Use-o quando precisar de uma precisão consistente em algarismos significativos, em vez de casas decimais.

import java.math.*;

MathContext mc = new MathContext(4, RoundingMode.HALF_UP);

BigDecimal a = new BigDecimal("1234567");
BigDecimal b = new BigDecimal("3");

BigDecimal result = a.divide(b, mc);
System.out.println(result); // 4.115E+5 (4 significant digits)

// DECIMAL32, DECIMAL64, DECIMAL128 are standard MathContexts
BigDecimal precise = new BigDecimal("355").divide(
    new BigDecimal("113"), MathContext.DECIMAL64);
System.out.println(precise); // 3.141592920353982...

Exemplo de carrinho de compras

Um cálculo completo de carrinho de compras usando BigDecimal: itens, imposto, desconto e total final.

import java.math.*;

record LineItem(String name, BigDecimal price, int qty) {
    BigDecimal subtotal() {
        return price.multiply(new BigDecimal(qty));
    }
}

var items = List.of(
    new LineItem("Laptop",  new BigDecimal("999.00"), 1),
    new LineItem("Case",    new BigDecimal("29.99"),  2),
    new LineItem("Charger", new BigDecimal("49.99"),  1)
);

BigDecimal subtotal = items.stream()
    .map(LineItem::subtotal)
    .reduce(BigDecimal.ZERO, BigDecimal::add);

BigDecimal taxRate = new BigDecimal("0.09");
BigDecimal tax = subtotal.multiply(taxRate).setScale(2, RoundingMode.HALF_UP);
BigDecimal total = subtotal.add(tax);

System.out.println("Subtotal: " + subtotal);
System.out.println("Tax:      " + tax);
System.out.println("Total:    " + total);

Stripe: moeda em centavos

Processadores de pagamento como Stripe armazenam os valores como centavos inteiros para evitar completamente problemas com decimais. Converter entre centavos e valores de exibição é um padrão comum.

import java.math.*;

// Store as cents (long) for database / API
long amountCents = 999_99L; // $999.99

// Convert to BigDecimal for display
BigDecimal amount = BigDecimal
    .valueOf(amountCents)
    .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);

System.out.println("Amount: $" + amount); // Amount: $999.99

// Convert user input back to cents
BigDecimal input = new BigDecimal("49.95");
long cents = input.multiply(new BigDecimal("100"))
    .setScale(0, RoundingMode.HALF_UP).longValueExact();
System.out.println("Cents: " + cents); // Cents: 4995

Quando usar BigDecimal em vez de double

Escolha o tipo adequado para cada finalidade:

  • BigDecimal: valores financeiros, impostos e faturas, quando a representação decimal exata é importante
  • double: cálculos científicos, gráficos e aprendizado de máquina — quando a velocidade é importante e pequenos erros são aceitáveis
  • int/long em centavos: APIs de pagamento e armazenamento de valores monetários em bancos de dados

Verificação rápida

Qual método de comparação de BigDecimal você deve usar para verificar se dois valores BigDecimal são numericamente iguais, independentemente da escala?

Recapitulação: BigDecimal para cálculos financeiros

Principais conclusões:

  • double/float causam erros de arredondamento — nunca os use para dinheiro
  • Crie BigDecimal a partir de String ou BigDecimal.valueOf(), não de double
  • Use add(), subtract(), multiply(), divide() para operações aritméticas
  • Sempre especifique a escala e RoundingMode ao dividir
  • Use compareTo() para verificar igualdade, não equals()
  • Considere armazenar dinheiro como centavos inteiros para operações com bancos de dados/APIs

Perguntas Frequentes

A aula “BigDecimal para Cálculos Financeiros” é grátis?

Sim — o texto completo de “BigDecimal para Cálculos Financeiros” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.

O que vou aprender em “BigDecimal para Cálculos Financeiros”?

Use BigDecimal para evitar erros de precisão de ponto flutuante em cálculos monetários e tributários. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Java Academy?

Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “BigDecimal para Cálculos Financeiros”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Java Academy?

Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Fundamentos da Classe Math
  2. Aritmética de Inteiros e Estouro
  3. BigDecimal para Cálculos Financeiros
  4. NumberFormat e printf
← Voltar para Java Academy