Classes

BigDecimal

Trabalhando com números decimais com precisão

BigDecimal é uma classe da API Java utilizada para representar números decimais com alta precisão, evitando problemas de arredondamento comuns nos tipos primitivos float e double.

Usamos BigDecimal principalmente quando o nosso modelo de negócio envolve valores financeiros, cálculos contábeis, monetários ou qualquer cenário onde precisão é obrigatória.

Exemplos de uso comuns:

  • Valores monetários: salários, preços, juros;
  • Cálculos financeiros: parcelas, impostos, descontos;
  • Sistemas bancários e contábeis.
    Não utilize double ou float para valores financeiros.

Os tipos double e float trabalham com aproximações binárias, o que pode gerar resultados inesperados, como:

System.out.println(0.1 + 0.2); // 0.30000000000000004

Com BigDecimal, esse problema não acontece.

Criando objetos BigDecimal

Como BigDecimal é uma classe, precisamos criar seus objetos explicitamente.

Forma correta (String)

BigDecimal valor = new BigDecimal("10.50");

Forma alternativa (valueOf)

BigDecimal valor = BigDecimal.valueOf(10.50);

Evite o construtor BigDecimal(double), pois ele herda o problema de precisão do double. ::

Não recomendado:

BigDecimal valor = new BigDecimal(10.50);

Operações com BigDecimal

Diferente dos tipos primitivos, não usamos operadores matemáticos (+, -, *, /).

As operações são feitas através de métodos:

Soma

BigDecimal valor1 = new BigDecimal("10.00");
BigDecimal valor2 = new BigDecimal("5.50");

BigDecimal resultado = valor1.add(valor2);
System.out.println(resultado); // 15.50

Subtração

BigDecimal resultado = valor1.subtract(valor2);

Multiplicação

BigDecimal resultado = valor1.multiply(valor2);

Divisão

BigDecimal resultado = valor1.divide(valor2);

⚠️ Atenção: nem toda divisão gera um valor exato.

Arredondamentos com BigDecimal

Quando uma divisão gera dízima, é obrigatório informar escala e modo de arredondamento.

BigDecimal valor1 = new BigDecimal("10");
BigDecimal valor2 = new BigDecimal("3");

BigDecimal resultado = valor1.divide(valor2, 2, RoundingMode.HALF_UP);
System.out.println(resultado); // 3.33

Principais modos de arredondamento

  • HALF_UP → arredonda para cima quando ≥ 5 (mais comum em finanças)
  • HALF_DOWN → arredonda para baixo quando = 5
  • HALF_EVEN → arredondamento bancário
  • DOWN → sempre trunca
  • UP → sempre arredonda para cima

Comparação de valores

Para comparar BigDecimal, não use equals em regras de negócio.

BigDecimal a = new BigDecimal("10.0");
BigDecimal b = new BigDecimal("10.00");

a.equals(b); // false

Use compareTo:

a.compareTo(b); // 0 (valores iguais)

Resultado do compareTo:

  • 0 → iguais
  • -1 → menor
  • 1 → maior

Boas práticas ao usar BigDecimal

  • Sempre prefira String ou valueOf no construtor;
  • Nunca use operadores matemáticos (+, -, *, /);
  • Defina explicitamente escala e arredondamento em divisões;
  • Use compareTo para comparações;
  • Trate BigDecimal como imutável (cada operação gera um novo objeto).

Exemplo 1

Simulação de cálculo de abastecimento de gasolina

Regras do cenário

  • O valor do litro possui 3 dígitos decimais (ex: 5.879)
  • A quantidade de litros pode ser decimal
  • O valor final deve ser arredondado para 2 casas decimais
  • Arredondamento financeiro (HALF_EVEN)
import java.math.BigDecimal;
import java.math.RoundingMode;

public class PostoCombustivel {

    public static void main(String[] args) {

        BigDecimal precoLitro = new BigDecimal("5.879");

        BigDecimal abastecimento1 = calcularValorCombustivel(precoLitro, new BigDecimal("10"));
        BigDecimal abastecimento2 = calcularValorCombustivel(precoLitro, new BigDecimal("23.45"));
        BigDecimal abastecimento3 = calcularValorCombustivel(precoLitro, new BigDecimal("42.7"));

        System.out.println("Abastecimento 1: R$ " + abastecimento1);
        System.out.println("Abastecimento 2: R$ " + abastecimento2);
        System.out.println("Abastecimento 3: R$ " + abastecimento3);
    }

    /**
     * Calcula o valor total do abastecimento
     *
     * @param valorLitro valor do litro do combustível (3 casas decimais)
     * @param quantidadeLitros quantidade abastecida
     * @return valor total a pagar (2 casas decimais)
     */
    public static BigDecimal calcularValorCombustivel(BigDecimal valorLitro,
                                                       BigDecimal quantidadeLitros) {

        BigDecimal valorTotal = valorLitro.multiply(quantidadeLitros);

        return valorTotal.setScale(2, RoundingMode.HALF_UP);
    }
}

Exemplo 2

Exemplo simples de cálculo de parcela (didático)

  • Valor total com 2 casas decimais
  • Cada parcela com 2 casas decimais
  • Arredondamento explícito
import java.math.BigDecimal;
import java.math.RoundingMode;

public class Parcelamento {

    public static void main(String[] args) {

        BigDecimal valorTotal = new BigDecimal("100.00");
        int quantidadeParcelas = 6;

        BigDecimal valorParcela = calcularValorParcela(valorTotal, quantidadeParcelas);

        System.out.println("Valor da parcela: R$ " + valorParcela);
    }

    public static BigDecimal calcularValorParcela(BigDecimal valorTotal,
                                                   int quantidadeParcelas) {

        return valorTotal.divide(
                BigDecimal.valueOf(quantidadeParcelas),
                2,
                RoundingMode.HALF_EVEN
        );
    }
}