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.9999999999999999Creació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.1Aritmé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.7676Modos 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 ceroCEILING— 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.57Divisió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.33Comparació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: 4995Cuá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
- Fundamentos de la clase Math
- Aritmética de enteros y desbordamiento
- BigDecimal para cálculos financieros
- NumberFormat y printf