BigDecimal for Financial Calculations
Use BigDecimal to avoid floating-point precision errors in money and tax calculations.
BigDecimal for Financial Calculations is a free Java Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
BigDecimal for Financial Calculations
Floating-point types (double, float) cannot represent all decimal values exactly due to binary representation. For money and taxes, use BigDecimal.
The Floating-Point Problem
Binary floating-point introduces tiny rounding errors. In financial apps these errors accumulate and cause real bugs.
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.9999999999999999Creating BigDecimal Safely
Always create BigDecimal from a String, not from a double. Using the double constructor inherits the floating-point imprecision.
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.1Basic Arithmetic with BigDecimal
BigDecimal uses method calls for arithmetic: add(), subtract(), multiply(), divide(). These return new BigDecimal instances (immutable).
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.7676Rounding Modes
RoundingMode controls how BigDecimal rounds. Key modes:
HALF_UP— standard rounding (0.5 rounds up)HALF_EVEN— banker's rounding (0.5 rounds to nearest even)DOWN— truncate toward zeroCEILING— round toward positive infinity
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.57Division and Scale
Division with BigDecimal requires specifying scale and rounding mode to avoid ArithmeticException for non-terminating decimals.
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.33Comparing BigDecimals
Use compareTo() to compare values, not equals(). equals() considers scale — 2.0 and 2.00 are NOT equal by equals() but ARE equal by 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 for Significant Digits
MathContext specifies precision (significant digits) and rounding mode. Use it when you need consistent significant-digit precision rather than decimal places.
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...Shopping Cart Example
A complete shopping cart calculation using BigDecimal: line items, tax, discount, and final total.
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: Currency in Cents
Payment processors like Stripe store amounts as integer cents to avoid decimal issues entirely. Converting between cents and display amounts is a common pattern.
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: 4995When to Use BigDecimal vs double
Choose the right type for the job:
- BigDecimal: financial amounts, taxes, invoices, where exact decimal representation matters
- double: scientific calculations, graphics, ML — where speed matters and small errors are acceptable
- int/long cents: payment APIs, database storage of money
Quick Check
Which BigDecimal comparison method should you use to check if two BigDecimal values are numerically equal, regardless of scale?
Recap: BigDecimal for Financial Calculations
Key takeaways:
- double/float cause rounding errors — never use them for money
- Create BigDecimal from String or BigDecimal.valueOf(), not from double
- Use add(), subtract(), multiply(), divide() for arithmetic
- Always specify scale and RoundingMode when dividing
- Use compareTo() for equality checks, not equals()
- Consider storing money as integer cents for database/API work
Frequently asked questions
Is the “BigDecimal for Financial Calculations” lesson free?
Yes — the full text of “BigDecimal for Financial Calculations” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “BigDecimal for Financial Calculations”?
Use BigDecimal to avoid floating-point precision errors in money and tax calculations. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “BigDecimal for Financial Calculations” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Math Class Essentials
- Integer Arithmetic & Overflow
- BigDecimal for Financial Calculations
- NumberFormat and printf