0Pricing
Java Academy · Lección

BigDecimal para cálculos financieros

Use BigDecimal para evitar errores de precisión de coma flotante en cálculos monetarios y fiscales.

BigDecimal para cálculos financieros es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

BigDecimal para cálculos financieros

Los tipos de coma flotante (double, float) no pueden representar exactamente todos los valores decimales debido a la representación binaria. Para el dinero y los impuestos, utilice BigDecimal.

El problema de la coma flotante

La coma flotante binaria introduce pequeños errores de redondeo. En las aplicaciones financieras, estos errores se acumulan y provocan errores reales.

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

Creación segura de BigDecimal

Cree siempre BigDecimal a partir de un String, no de un double. El uso del constructor que recibe un double hereda la imprecisión de la coma flotante.

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 con BigDecimal

BigDecimal utiliza llamadas a métodos para realizar operaciones aritméticas: add(), subtract(), multiply() y divide(). Estos métodos devuelven nuevas instancias de BigDecimal (es inmutable).

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 redondeo

RoundingMode controla cómo redondea BigDecimal. Modos principales:

  • HALF_UP — redondeo estándar (0.5 se redondea hacia arriba)
  • HALF_EVEN — redondeo bancario (0.5 se redondea al número par más cercano)
  • DOWN — trunca hacia cero
  • CEILING — redondea hacia el 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

División y escala

La división con BigDecimal requiere especificar la escala y el modo de redondeo para evitar ArithmeticException en el caso de decimales no 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

Comparación de BigDecimal

Utilice compareTo() para comparar valores, no equals(). equals() tiene en cuenta la escala: 2.0 y 2.00 NO son iguales según equals(), pero SÍ son iguales según 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 cifras significativas

MathContext especifica la precisión (cifras significativas) y el modo de redondeo. Utilícelo cuando necesite una precisión coherente en cifras significativas en lugar de un número fijo de posiciones decimales.

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...

Ejemplo de carrito de compras

Un cálculo completo de un carrito de compras mediante BigDecimal: artículos, impuestos, descuento y 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: moneda en centavos

Los procesadores de pagos como Stripe almacenan los importes como centavos enteros para evitar por completo los problemas de los decimales. La conversión entre centavos e importes para mostrar es un patrón habitual.

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

Cuándo utilizar BigDecimal en lugar de double

Elija el tipo adecuado para cada tarea:

  • BigDecimal: importes financieros, impuestos y facturas, cuando es importante una representación decimal exacta
  • double: cálculos científicos, gráficos y ML, cuando la velocidad es importante y se aceptan pequeños errores
  • int/long en centavos: API de pagos y almacenamiento de dinero en bases de datos

Comprobación rápida

¿Qué método de comparación de BigDecimal debe utilizar para comprobar si dos valores BigDecimal son numéricamente iguales, independientemente de la escala?

Repaso: BigDecimal para cálculos financieros

Conceptos clave:

  • double/float provocan errores de redondeo; nunca los utilice para representar dinero
  • Cree BigDecimal a partir de String o mediante BigDecimal.valueOf(), no a partir de double
  • Utilice add(), subtract(), multiply() y divide() para las operaciones aritméticas
  • Especifique siempre la escala y RoundingMode al realizar divisiones
  • Utilice compareTo() para comprobar la igualdad, no equals()
  • Considere almacenar el dinero como centavos enteros para trabajar con bases de datos y API

Preguntas frecuentes

¿La lección «BigDecimal para cálculos financieros» es gratis?

Sí — el texto completo de «BigDecimal para cálculos financieros» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «BigDecimal para cálculos financieros»?

Use BigDecimal para evitar errores de precisión de coma flotante en cálculos monetarios y fiscales. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «BigDecimal para cálculos financieros»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Fundamentos de la clase Math
  2. Aritmética de enteros y desbordamiento
  3. BigDecimal para cálculos financieros
  4. NumberFormat y printf
← Volver a Java Academy