Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to truncate double to N decimal places?

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 apparently RoundingMode.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:

  1. 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 having BigDecimal?

  2. How do I correctly truncate my values?

Thanks.

like image 212
SqueezyMo Avatar asked Aug 01 '15 14:08

SqueezyMo


2 Answers

"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()
}
like image 112
user1886323 Avatar answered Oct 14 '22 20:10

user1886323


Multiply the number with pow(10,n) and store it in integer type & then again divide it by pow(10,n)

like image 34
Priyanshu Jha Avatar answered Oct 14 '22 19:10

Priyanshu Jha