I found that a rounding error with my Java application. The method used to round was:
public static double round(double value,double precision)
{
return Math.round(value * precision) / precision;
}
This could have an error (i.e. round(138.515,100) should return 138.52, and returns 138.51) So I've created the following rounder:
// Mikeldi's rounder
public static double round2DecimalPlaces(double value,int decimalPlaces)
{
int s = value<0?-1:1;
double p = 1;
for (int i = 0; i < decimalPlaces; i++) {
p*=10;
}
double n = (long) value;
double d = ((value*10*p)-(n*10*p));
d +=s*5;
d /= 10;
d = (long)d;
d /= p;
return d+n;
}
I created this method since other rounding methods added too much latency to the system (low latency system). This one is around 10 times faster than the previous.
Note: This rounder will only use to round to possitive decimalPlaces (or 0).
Is there any problems I haven't see with this new rounder?
Thanks,
1 Answer 1
The Math#round method is not broken. 138.515 can't be exactly represented as a double. To see the exact value, you can use:
System.out.println(new BigDecimal(138.515d));
which prints:
138.5149999999999863575794734060764312744140625
It is therefore accurate for round to return 138.51. If you need more precision than double can give, you can use BigDecimal.
EDIT
If BigDecimal is not an option, and if the number of decimals is smallish (say 3 or 4 because these are prices for example), you can use longs instead with the last 4 digits being the decimals. So 138.51d would be 1385100L instead.
Is there any problems I haven't see with this new rounder?It depends what you want to achive... Fisrt of all you should write some unit test that will compare yours method output with the trusted method that you want to make run faster. And then look into everything that does not match and think about if those differences, if they exist, are acceptable or not.