Explain Codes LogoExplain Codes Logo

How to round a number to n decimal places in Java

java
rounding
decimalformat
bigdecimal
Anton ShumikhinbyAnton Shumikhin·Oct 1, 2024
TLDR

In Java, for precise rounding to n decimal places, use:

BigDecimal rounded = new BigDecimal(value).setScale(n, RoundingMode.HALF_UP);

Here, value is your number, n is the number of decimal places, and RoundingMode.HALF_UP is the typical rounding method. Adjust n and RoundingMode as required.

To visualize this, let's round 88.125927 to 2 decimal places:

BigDecimal value = new BigDecimal("88.125927"); value = value.setScale(2, RoundingMode.HALF_UP); // Output: 88.13 // To the next station, folks!

Digging deeper into rounding in Java

Gentle introduction to DecimalFormat

DecimalFormat is a robust goody bag for formatting numbers. It is capable of handling rounding and formatting simultaneously, cutting unnecessary steps.

// Creating DecimalFormat object with "#.##" pattern, because we care about our CPU cycles DecimalFormat df = new DecimalFormat("#.##"); // HALF_UP - Because Caesar only looks forward! df.setRoundingMode(RoundingMode.HALF_UP); // Formatted to exactly the way humans want it. String formatted = df.format(123.45678); // Output: "123.46"

Remember, use the #.## pattern in DecimalFormat to get rid of trailing zeroes.

Double, double toil, and troubles

double and float types, essentially, are your moody teenagers of Java. They tend to mess things up if not handled with care. That's why we add a small 1e-6 to double numbers to improve precision and calm them down.

// The number that needs understanding and love double number = 100.123456789; // Adding a little pixie dust for good luck double adjusted = number + 1e-6;

Then convert it to a BigDecimal or apply a DecimalFormat.

We're always optimistic here - Rounding up

When the requirement is to always round upwards, regardless of how large the decimal is - we use RoundingMode.CEILING, because the sky is the limit.

// Always looking up! BigDecimal roundedCeil = new BigDecimal(value).setScale(n, RoundingMode.CEILING);

BigDecimal - The big daddy

Precision is paramount in financial applications. That's precisely what BigDecimal shines bright at by offering tight control over the rounding behavior.

// The total price of our imaginary island BigDecimal price = BigDecimal.valueOf(10.755); // After consulting with our accountant, we round it up to just 2 places price = price.setScale(2, BigDecimal.ROUND_HALF_UP);

Remember, BigDecimal.valueOf(double) is granny's secret recipe as opposed to new BigDecimal(double) when it comes to dealing with inconsistentities of double values.

Pro-tips on robust rounding techniques

Avoiding pitfalls

Math.round() should be reserved only for float/double values for risk-free rounding. However, BigDecimal is the way to go when accuracy is crucial. Always cross-check your rounding manually with test cases to be on the safe side.

// Lemme show you a magic trick! // We will turn this float into an accurate number // No abracadabra required! BigDecimal rounded = new BigDecimal(floatNumber).setScale(2, RoundingMode.HALF_UP);

Let's talk BigDecimal

The MathContext class

MathContext is a fancy dinner jacket for BigDecimal. It allows you to specify the precision and the rounding mode together when performing operations.

// Oh look, a smart-looking BigDecimal! MathContext mc = new MathContext(3, RoundingMode.HALF_UP); BigDecimal value = new BigDecimal("2.34567"); // Alan Turing would be proud! BigDecimal result = value.round(mc); // Output: 2.35

Strip off the zeroes, will you?

To remove any stubborn zeros that stick around even after rounding, you sneakily use the stripTrailingZeros() method.

// This BigDecimal feels a bit bloated, wouldn't you say? BigDecimal value = new BigDecimal("2.5000"); // Fear no more, for I have scissors! value = value.setScale(3, BigDecimal.ROUND_HALF_UP).stripTrailingZeros();

'Neat and tidy' is the way of life, ain't it?

Remainders: The unsung heroes

BigDecimal.remainder() helps to check the rounding accuracy and mitigating modulus errors. Especially useful when dealing with monetary calculations so that you won't lose that precious penny!

// I owe you some money, let's see how much I can pay per installment BigDecimal payment = new BigDecimal("100.50"); BigDecimal installment = new BigDecimal("33.33"); // Oh, look at these left overs BigDecimal remainder = payment.remainder(installment);

Using BigDecimal's toString methods strategically

Converting BigDecimal to String using toPlainString() results in a non-scientific output, very human-readable if you may say.

BigDecimal money = new BigDecimal("123456789.12300"); // Readable version for us Humanfolk String plainStr = money.toPlainString();

On the other hand, toString() can also be used to strip any insignificant trailing zeros. It's a sweet lollipop after the doctor's routine check-up. Nothing to worry about!

BigDecimal value = new BigDecimal("123456.789000"); // Voila! Extra zeros be gone! String trimmedStr = value.toString();