Here's an utility that rounds (instead of truncating) a double to specified number of decimal places.
For example:
Use with AIround(200.3456, 2); // returns 200.35
Original version; watch out with this
Use with AIpublic static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
value = value * factor;
long tmp = Math.round(value);
return (double) tmp / factor;
}
This breaks down badly in corner cases with either a very high number of decimal places (e.g. round(1000.0d, 17)) or large integer part (e.g. round(90080070060.1d, 9)). Thanks to Sloin for pointing this out.
I've been using the above to round "not-too-big" doubles to 2 or 3 decimal places happily for years (for example to clean up time in seconds for logging purposes: 27.987654321987 -> 27.99). But I guess it's best to avoid it, since more reliable ways are readily available, with cleaner code too.
So, use this instead
(Adapted from this answer by Louis Wasserman and this one by Sean Owen.)
Use with AIpublic static double round(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();
}
Note that HALF_UP is the rounding mode "commonly taught at school". Peruse the RoundingMode documentation, if you suspect you need something else such as Bankers’ Rounding.
Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
And in every case
Always remember that floating point representations using float and double are inexact.
For example, consider these expressions:
Use with AI999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
For exactness, you want to use BigDecimal. And while at it, use the constructor that takes a String, never the one taking double. For instance, try executing this:
Use with AISystem.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));
Some excellent further reading on the topic:
- Item 48: "Avoid
floatanddoubleif exact answers are required" in Effective Java (2nd ed) by Joshua Bloch - What Every Programmer Should Know About Floating-Point Arithmetic
If you wanted String formatting instead of (or in addition to) strictly rounding numbers, see the other answers.
Specifically, note that round(200, 0) returns 200.0. If you want to output "200.00", you should first round and then format the result for output (which is perfectly explained in Jesper's answer).
Here's an utility that rounds (instead of truncating) a double to specified number of decimal places.
For example:
Use with AIround(200.3456, 2); // returns 200.35
Original version; watch out with this
Use with AIpublic static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
value = value * factor;
long tmp = Math.round(value);
return (double) tmp / factor;
}
This breaks down badly in corner cases with either a very high number of decimal places (e.g. round(1000.0d, 17)) or large integer part (e.g. round(90080070060.1d, 9)). Thanks to Sloin for pointing this out.
I've been using the above to round "not-too-big" doubles to 2 or 3 decimal places happily for years (for example to clean up time in seconds for logging purposes: 27.987654321987 -> 27.99). But I guess it's best to avoid it, since more reliable ways are readily available, with cleaner code too.
So, use this instead
(Adapted from this answer by Louis Wasserman and this one by Sean Owen.)
Use with AIpublic static double round(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();
}
Note that HALF_UP is the rounding mode "commonly taught at school". Peruse the RoundingMode documentation, if you suspect you need something else such as Bankers’ Rounding.
Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
And in every case
Always remember that floating point representations using float and double are inexact.
For example, consider these expressions:
Use with AI999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
For exactness, you want to use BigDecimal. And while at it, use the constructor that takes a String, never the one taking double. For instance, try executing this:
Use with AISystem.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));
Some excellent further reading on the topic:
- Item 48: "Avoid
floatanddoubleif exact answers are required" in Effective Java (2nd ed) by Joshua Bloch - What Every Programmer Should Know About Floating-Point Arithmetic
If you wanted String formatting instead of (or in addition to) strictly rounding numbers, see the other answers.
Specifically, note that round(200, 0) returns 200.0. If you want to output "200.00", you should first round and then format the result for output (which is perfectly explained in Jesper's answer).
If you just want to print a double with two digits after the decimal point, use something like this:
Use with AIdouble value = 200.3456;
System.out.printf("Value: %.2f", value);
If you want to have the result in a String instead of being printed to the console, use String.format() with the same arguments:
Use with AIString result = String.format("%.2f", value);
Or use class DecimalFormat:
Use with AIDecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
Just use: (easy as pie)
double number = 651.5176515121351;
number = Math.round(number * 100);
number = number/100;
The output will be 651.52
Are you working with money? Creating a String and then converting it back is pretty loopy.
Use BigDecimal. This has been discussed quite extensively. You should have a Money class and the amount should be a BigDecimal.
Even if you're not working with money, consider BigDecimal.
Use setRoundingMode, set the RoundingMode explicitly to handle your issue with the half-even round, then use the format pattern for your required output.
Example:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
gives the output:
12
123.1235
0.23
0.1
2341234.2125
EDIT: The original answer does not address the accuracy of the double values. That is fine if you don't care much whether it rounds up or down. But if you want accurate rounding, then you need to take the expected accuracy of the values into account. Floating point values have a binary representation internally. That means that a value like 2.7735 does not actually have that exact value internally. It can be slightly larger or slightly smaller. If the internal value is slightly smaller, then it will not round up to 2.7740. To remedy that situation, you need to be aware of the accuracy of the values that you are working with, and add or subtract that value before rounding. For example, when you know that your values are accurate up to 6 digits, then to round half-way values up, add that accuracy to the value:
Double d = n.doubleValue() + 1e-6;
To round down, subtract the accuracy.
Assuming value is a double, you can do:
(double)Math.round(value * 100000d) / 100000d
That's for 5 digits precision. The number of zeros indicate the number of decimals.