How to truncate double to N decimal places?
Solution 1
"in particular to avoide the expensive conversion to String and back" - This is exactly what avoids the loss of precision. You can't get arbitrary precision for free.
If you need arbitrary precision then you should not use double
but instead do:
static String truncate(String value, int places) {
return new BigDecimal(value)
.setScale(places, RoundingMode.DOWN)
.stripTrailingZeros()
.toString()
}
Solution 2
Multiply the number with pow(10,n)
and store it in integer type & then again divide it by pow(10,n)
Solution 3
Truncating a double
to N decimal places is not really a question that makes any sense, because simple decimal numbers (e.g. 0.3
) cannot be represented as double
s.
If you want to know the true value of the double
0.3
you can do
System.out.println(new BigDecimal(0.3));
and you will see that it is really
0.299999999999999988897769753748434595763683319091796875
So 0.299
is the correct answer.
This question only really makes sense using BigDecimal
and giving the answer as a BigDecimal
or a String
, not a double
. @user1886323's answer shows how to do this.
SqueezyMo
Updated on June 04, 2022Comments
-
SqueezyMo almost 2 years
I want to round my double value down to N decimal places (say, one), esentially just leaving out all the digits that follow:
0.123 #=> 0.1 0.19 #=> 0.1 0.2 #=> 0.2
This question has been brought up numerous times, for example here and here. The recommended approach is to use
BigDecimal
and then scale it, in particular to avoid expensive converting to string and back. The rounding mode I need is apparentlyRoundingMode.DOWN
.So the method is something like this:
static double truncate(double value, int places) { return new BigDecimal(value) .setScale(places, RoundingMode.DOWN) .doubleValue(); }
But, due to the loss of precision, it returns somewhat unexpected results:
truncate(0.2, 1) #=> 0.2 truncate(0.3, 1) #=> 0.2 truncate(0.4, 1) #=> 0.4 truncate(0.2, 3) #=> 0.2 truncate(0.3, 3) #=> 0.299 truncate(0.4, 3) #=> 0.4
This begs for two questions:
Is it how it's supposed to work for
0.3
? Why would there be a loss of precision in this case? Doesn't it defeat the whole purpose of havingBigDecimal
?How do I correctly truncate my values?
Thanks.