javaoptimizationroundingfloating-accuracy

What is the most efficient way to round a float value to the nearest integer in java?


I've seen a lot of discussion on SO related to rounding float values, but no solid Q&A considering the efficiency aspect. So here it is:

What is the most efficient (but correct) way to round a float value to the nearest integer?

(int) (mFloat + 0.5);

or

Math.round(mFloat);

or

FloatMath.floor(mFloat + 0.5);

or something else?

Preferably I would like to use something available in standard java libraries, not some external library that I have to import.


Solution

  • public class Main {
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < 10; i++) {
                measurementIteration();
            }
        }
    
        public static void measurementIteration() {
            long s, t1 = 0, t2 = 0;
            float mFloat = 3.3f;
            int f, n1 = 0, n2 = 0;
            for (int i = 0; i < 1E4; i++) {
                switch ((int) (Math.random() * 2)) {
                case 0:
                    n1 += 1;
                    s = System.currentTimeMillis();
                    for (int k = 0; k < 1E4; k++)
                        f = (int) (mFloat + 0.5);
                    t1 += System.currentTimeMillis() - s;
                    break;
                case 1:
                    n2 += 1;
                    s = System.currentTimeMillis();
                    for (int k = 0; k < 1E4; k++)
                        f = Math.round(mFloat);
                    t2 += System.currentTimeMillis() - s;
                    break;
                }
            }
            System.out.println(String.format("(int) (mFloat + 0.5): n1 = %d    -> %.3fms per call", n1, t1 * 1000.0 / n1));
            System.out.println(String.format("Math.round(mFloat)  : n2 = %d    -> %.3fms per call", n2, t2 * 1000.0 / n2));
        }
    }
    

    Output on Java SE6:

    (int) (mFloat + 0.5): n1 = 50041    -> 30ms per call
    Math.round(mFloat)  : n2 = 49959    -> 220ms per call
    

    Output on Java SE7 (thanks to alex for the results):

    (int) (mFloat + 0.5): n1 = 50120000 -> 20ms per call
    Math.round(mFloat) : n2 = 49880000 -> 20ms per call
    

    As you can see, there was a huge performance improvement on Math.round from SE6 to SE7. I think in SE7 there is no significant difference anymore and you should choose whatever seems more readable to you.