Complete guide to Java rounding with Math, BigDecimal, and DecimalFormat
Java provides multiple approaches for rounding numbers, from simple Math class methods to precise BigDecimal operations for financial calculations. Understanding when and how to use each method is crucial for accurate and reliable numeric operations.
round(), ceil(), floor()
Precise financial rounding
Display formatting
Math.round(double a) // returns long
Math.round(float a) // returns intMath.round() returns the closest integer to the argument. For ties (exactly .5), it rounds up.
// Round to nearest integer System.out.println(Math.round(3.14)); // Output: 3 System.out.println(Math.round(3.7)); // Output: 4 System.out.println(Math.round(3.5)); // Output: 4 (rounds up) System.out.println(Math.round(2.5)); // Output: 3 (rounds up) // Negative numbers System.out.println(Math.round(-3.5)); // Output: -3 (rounds toward 0) System.out.println(Math.round(-3.7)); // Output: -4 // Return types long resultLong = Math.round(3.14); // long int resultInt = Math.round(3.14f); // int
/**
* Round double to specified decimal places
*/
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
double tmp = value * factor;
return Math.round(tmp) / (double) factor;
}
// Usage
System.out.println(round(3.14159, 2)); // 3.14
System.out.println(round(12.567, 1)); // 12.6
System.out.println(round(99.999, 2)); // 100.0Math.ceil(double a) // returns doubleReturns the smallest double value that is greater than or equal to the argument (ceiling).
// Round up to integer System.out.println(Math.ceil(3.1)); // 4.0 System.out.println(Math.ceil(3.9)); // 4.0 System.out.println(Math.ceil(3.0)); // 3.0 // Negative numbers (toward positive infinity) System.out.println(Math.ceil(-3.1)); // -3.0 System.out.println(Math.ceil(-3.9)); // -3.0 // Convert to int if needed int result = (int) Math.ceil(3.7); // 4
Math.floor(double a) // returns doubleReturns the largest double value that is less than or equal to the argument (floor).
// Round down to integer System.out.println(Math.floor(3.9)); // 3.0 System.out.println(Math.floor(3.1)); // 3.0 System.out.println(Math.floor(3.0)); // 3.0 // Negative numbers (toward negative infinity) System.out.println(Math.floor(-3.1)); // -4.0 System.out.println(Math.floor(-3.9)); // -4.0 // Convert to int if needed int result = (int) Math.floor(3.7); // 3
BigDecimal provides arbitrary-precision decimal arithmetic, essential for financial calculations where precision is critical. It offers complete control over rounding behavior through RoundingMode.
Floating-point types (float, double) cannot represent all decimal numbers exactly, leading to precision errors:
// Floating-point precision issues
System.out.println(0.1 + 0.2); // 0.30000000000000004
// BigDecimal solution
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b)); // 0.3 (exact!)import java.math.BigDecimal;
import java.math.RoundingMode;
// Create BigDecimal
BigDecimal value = new BigDecimal("12.3456");
// Round to 2 decimal places - HALF_UP
BigDecimal rounded = value.setScale(2, RoundingMode.HALF_UP);
System.out.println(rounded); // 12.35
// Different rounding modes
value = new BigDecimal("12.345");
System.out.println(value.setScale(2, RoundingMode.UP)); // 12.35
System.out.println(value.setScale(2, RoundingMode.DOWN)); // 12.34
System.out.println(value.setScale(2, RoundingMode.HALF_UP)); // 12.35
System.out.println(value.setScale(2, RoundingMode.HALF_DOWN)); // 12.34
System.out.println(value.setScale(2, RoundingMode.HALF_EVEN)); // 12.34BigDecimal val = new BigDecimal("2.675");
// HALF_UP - Round 5 up (traditional)
val.setScale(2, RoundingMode.HALF_UP); // 2.68
// HALF_DOWN - Round 5 down
val.setScale(2, RoundingMode.HALF_DOWN); // 2.67
// HALF_EVEN - Banker's rounding (round to even)
val.setScale(2, RoundingMode.HALF_EVEN); // 2.68
// UP - Always round away from zero
val.setScale(2, RoundingMode.UP); // 2.68
// DOWN - Always round toward zero
val.setScale(2, RoundingMode.DOWN); // 2.67
// CEILING - Always toward positive infinity
val.setScale(2, RoundingMode.CEILING); // 2.68
// FLOOR - Always toward negative infinity
val.setScale(2, RoundingMode.FLOOR); // 2.67
// UNNECESSARY - Throws exception if rounding needed
// val.setScale(2, RoundingMode.UNNECESSARY); // ArithmeticException!import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* Round double to decimal places using BigDecimal
*/
public static double roundBigDecimal(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
// Usage
System.out.println(roundBigDecimal(3.14159, 2)); // 3.14
System.out.println(roundBigDecimal(2.675, 2)); // 2.68 (correct!)
System.out.println(roundBigDecimal(99.999, 2)); // 100.0DecimalFormat is used to format decimal numbers for display. It converts numbers to strings with specific patterns, ideal for UI presentation.
DecimalFormat df = new DecimalFormat(pattern);import java.text.DecimalFormat;
// Pattern: "0.00" - always 2 decimals with leading/trailing zeros
DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(3.14159)); // "3.14"
System.out.println(df.format(3.1)); // "3.10"
System.out.println(df.format(0.5)); // "0.50"
System.out.println(df.format(1234.5)); // "1234.50"
// Pattern: "#.##" - up to 2 decimals, no trailing zeros
DecimalFormat df2 = new DecimalFormat("#.##");
System.out.println(df2.format(3.14159)); // "3.14"
System.out.println(df2.format(3.1)); // "3.1"
System.out.println(df2.format(3.0)); // "3"
System.out.println(df2.format(0.5)); // "0.5"import java.text.DecimalFormat;
// Currency format with thousand separators
DecimalFormat currency = new DecimalFormat("$#,##0.00");
System.out.println(currency.format(1234.5)); // "$1,234.50"
System.out.println(currency.format(1234567.89)); // "$1,234,567.89"
// Percentage format
DecimalFormat percent = new DecimalFormat("#.##%");
System.out.println(percent.format(0.1234)); // "12.34%"
System.out.println(percent.format(0.5)); // "50%"
// Scientific notation
DecimalFormat scientific = new DecimalFormat("0.00E0");
System.out.println(scientific.format(1234.5)); // "1.23E3"DecimalFormat is for display only. It returns a string, not a number. For calculations, use BigDecimal or Math methods.
| Method | Return Type | Best For | Precision |
|---|---|---|---|
| Math.round() | long/int | Simple rounding | Approximate |
| Math.ceil()/floor() | double | Directional rounding | Approximate |
| BigDecimal | BigDecimal | Financial calculations | Exact |
| DecimalFormat | String | Display formatting | Display only |
import java.math.BigDecimal;
import java.math.RoundingMode;
public class OrderCalculator {
public static BigDecimal calculateTotal(
BigDecimal subtotal,
BigDecimal taxRate
) {
BigDecimal tax = subtotal.multiply(taxRate);
tax = tax.setScale(2, RoundingMode.HALF_UP);
BigDecimal total = subtotal.add(tax);
return total.setScale(2, RoundingMode.HALF_UP);
}
public static void main(String[] args) {
BigDecimal subtotal = new BigDecimal("99.99");
BigDecimal taxRate = new BigDecimal("0.085");
BigDecimal total = calculateTotal(subtotal, taxRate);
System.out.println("Total: $" + total); // Total: $108.49
}
}public class MeasurementCalculator {
/**
* Round measurement to specified precision
*/
public static double roundMeasurement(double value, int decimals) {
long factor = (long) Math.pow(10, decimals);
return Math.round(value * factor) / (double) factor;
}
public static void main(String[] args) {
// Temperature conversion
double celsius = 25.6789;
double fahrenheit = (celsius * 9.0 / 5.0) + 32;
System.out.println("Temperature: " +
roundMeasurement(fahrenheit, 1) + "°F");
// Output: Temperature: 78.2°F
}
}public class DataProcessor {
public static int calculatePageNumber(int itemIndex, int itemsPerPage) {
// Use floor for page calculation
return (int) Math.floor(itemIndex / (double) itemsPerPage);
}
public static int calculateTotalPages(int totalItems, int itemsPerPage) {
// Use ceiling for total pages
return (int) Math.ceil(totalItems / (double) itemsPerPage);
}
public static void main(String[] args) {
int totalItems = 47;
int itemsPerPage = 10;
int pages = calculateTotalPages(totalItems, itemsPerPage);
System.out.println("Total pages: " + pages); // Total pages: 5
int pageOfItem25 = calculatePageNumber(25, itemsPerPage);
System.out.println("Item 25 on page: " + pageOfItem25); // page: 2
}
}import java.text.DecimalFormat;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class ReportFormatter {
private static final DecimalFormat CURRENCY =
new DecimalFormat("$#,##0.00");
private static final DecimalFormat PERCENT =
new DecimalFormat("#0.00%");
public static void printReport(
BigDecimal revenue,
BigDecimal expenses
) {
BigDecimal profit = revenue.subtract(expenses);
BigDecimal margin = profit.divide(revenue, 4, RoundingMode.HALF_UP);
System.out.println("Revenue: " + CURRENCY.format(revenue));
System.out.println("Expenses: " + CURRENCY.format(expenses));
System.out.println("Profit: " + CURRENCY.format(profit));
System.out.println("Margin: " + PERCENT.format(margin));
}
public static void main(String[] args) {
BigDecimal revenue = new BigDecimal("1234567.89");
BigDecimal expenses = new BigDecimal("987654.32");
printReport(revenue, expenses);
// Output:
// Revenue: $1,234,567.89
// Expenses: $987,654.32
// Profit: $246,913.57
// Margin: 20.00%
}
}Financial calculations require exact decimal arithmetic. Use BigDecimal with RoundingMode.HALF_UP for consistent and accurate results.
Always use new BigDecimal("12.34") with strings, not new BigDecimal(12.34) with doubles, to avoid precision issues.
Always specify a RoundingMode when using BigDecimal to make rounding behavior explicit and predictable.
DecimalFormat is for formatting output. Don't use it for calculations - it returns strings.
Use Math methods for speed, BigDecimal for precision, and DecimalFormat for display formatting.
Complete guide to Python rounding methods
Python rounding ecosystem guide
JavaScript rounding to 2 decimal places
Complete JavaScript rounding guide
Python floor rounding techniques
Python 2 decimal place rounding