What is the fastest way to round to three decimal places?

The SO community was right, profiling your code before you ask performance questions seems to make more sense than my random guessing approach :-) I profiled my code (very intense math) and did not understand more than 70% of my code, by - apparently, in the part that I did not think about, it was a source of deceleration, rounding of decimal places.

static double roundTwoDecimals(double d) { DecimalFormat twoDForm = new DecimalFormat("#.###"); return Double.valueOf(twoDForm.format(d)); } 

My problem is that I get decimal numbers that are usually equal to .01, .02, etc., but sometimes I get something like .070000000001 (I really care only about the accuracy of 0.07, but with floating a comma causes my other formulas to crash) I just want the first 3 decimal places to avoid this problem.

So is there a better / faster way to do this?

+8
java
source share
2 answers

The standard way to round (positive) numbers would be something like this:

 double rounded = floor(1000 * doubleVal + 0.5) / 1000; 

Example 1: floor(1000 * .1234 + 0.5) / 1000 = floor(123.9)/1000 = 0.123
Example 2: floor(1000 * .5678 + 0.5) / 1000 = floor(568.3)/1000 = 0.568

But, as @nuakh commented, you will suffer some degree of rounding errors. If you want exactly 3 decimal places, it is best to convert to thousandths (i.e., Multiply everything by 1000) and use the integral data type ( int , long , etc.)

In this case, you would skip the final division by 1000 and use the integral values 123 and 568 for your calculations. If you want the results to be presented as percentages, you would divide by 10 to display:

123 → 12.3%
568 → 56.8%

+15
source share

Using a throw is faster than using a floor or round. I suspect casting is more optimized by the HotSpot compiler.

 public class Main { public static final int ITERS = 1000 * 1000; public static void main(String... args) { for (int i = 0; i < 3; i++) { perfRoundTo3(); perfCastRoundTo3(); } } private static double perfRoundTo3() { double sum = 0.0; long start = 0; for (int i = -20000; i < ITERS; i++) { if (i == 0) start = System.nanoTime(); sum += roundTo3(i * 1e-4); } long time = System.nanoTime() - start; System.out.printf("Took %,d ns per round%n", time / ITERS); return sum; } private static double perfCastRoundTo3() { double sum = 0.0; long start = 0; for (int i = -20000; i < ITERS; i++) { if (i == 0) start = System.nanoTime(); sum += castRoundTo3(i * 1e-4); } long time = System.nanoTime() - start; System.out.printf("Took %,d ns per cast round%n", time / ITERS); return sum; } public static double roundTo3(double d) { return Math.round(d * 1000 + 0.5) / 1000.0; } public static double castRoundTo3(double d) { return (long) (d * 1000 + 0.5) / 1000.0; } } 

prints

 Took 22 ns per round Took 9 ns per cast round Took 23 ns per round Took 6 ns per cast round Took 20 ns per round Took 6 ns per cast round 

Note: as of Java 7, the floor (x + 0.5) and round (x) are not doing the same thing as in this issue. Why Math.round (0.4999999999999999994) returns 1

This will correctly round up to a presentation error. This means that although the result is not accurate, a decimal number, for example. 0.001 doesn't seem to be accurate when you use toString (), it will fix it. Its only when you convert to BigDecimal or perform an arithmetic operation, you will see this view error.

+3
source share

All Articles