java-round-decimal-number
How to Round a Number to N Decimal Places in Java
Further reading:
Number of Digits in an Integer in Java
Learn different ways of getting the number of digits in an Integer in Java.
Check If a Number Is Prime in Java
Learn how to check the primality of the number using Java.
Check If a String Is Numeric in Java
Explore different ways to determine whether a String is numeric or not.
2. Decimal Numbers in Java
Java provides two primitive types that can be used for storing decimal numbers: float and double. Double is the type used by default:
double PI = 3.1415;
However, both types should never be used for precise values, such as currencies. For that, and also for rounding, we can use the BigDecimal class.
3. Formatting a Decimal Number
If we just want to print a decimal number with n digits after decimal point, we can simply format the output String:
System.out.printf("Value with 3 digits after decimal point %.3f %n", PI);
// OUTPUTS: Value with 3 digits after decimal point 3.142
Alternatively, we can format the value with the DecimalFormat class:
DecimalFormat df = new DecimalFormat("###.###");
System.out.println(df.format(PI));
DecimalFormat allows us to explicitly set rounding behavior, giving more control of the output than String.format() used above.
4. Rounding Doubles with BigDecimal
private static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(Double.toString(value));
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
There is one important thing to notice in this solution – when constructing BigDecimal; we must always use BigDecimal(String) constructor. This prevents issues with representing inexact values.
We can achieve the same by using the Apache Commons Math library:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.5</version>
</dependency>
The latest version can be found here.
Once the library is added to the project, we can use the Precision.round() method, which takes two arguments – value and scale:
Precision.round(PI, 3);
By default, it is using the same HALF_UP rounding method as our helper method. Therefore, the results should be the same.
Note that we can change rounding behavior by passing the desired rounding method as a third parameter.
5. Rounding Doubles with DoubleRounder
DoubleRounder is a utility in the decimal4j library. It provides a fast and garbage-free method for rounding doubles from 0 to 18 decimal points.
We can get the library (the latest version can be found here) by adding the dependency to the pom.xml:
<dependency>
<groupId>org.decimal4j</groupId>
<artifactId>decimal4j</artifactId>
<version>1.0.3</version>
</dependency>
Now, we can simply use:
DoubleRounder.round(PI, 3);
However, DoubleRounder fails in a few scenarios, for example:
System.out.println(DoubleRounder.round(256.025d, 2));
// OUTPUTS: 256.02 instead of expected 256.03
6. Math.Round() Method
In this case, we can control n number of decimal places by multiplying and dividing by 10^n:
public static double roundAvoid(double value, int places) {
double scale = Math.pow(10, places);
return Math.round(value * scale) / scale;
}
This method is not recommended as it’s truncating the value. In many cases values are rounded incorrectly:
System.out.println(roundAvoid(1000.0d, 17));
// OUTPUTS: 92.23372036854776 !!
System.out.println(roundAvoid(260.775d, 2));
// OUTPUTS: 260.77 instead of expected 260.78
And so, this method is listed here for learning purposes only.
7. Conclusion
We can simply format the output without changing the value, or we can round the variable by using a helper method. We’ve also covered a few libraries that deal with this problem.
The code used during the discussion can be found over on GitHub.