Why is if (variable1 % variable2 == 0) inefficient?

前端 未结 4 1125
我寻月下人不归
我寻月下人不归 2021-01-29 18:51

I am new to java, and was running some code last night, and this really bothered me. I was building a simple program to display every X outputs in a for loop, and I noticed a MA

4条回答
  •  抹茶落季
    2021-01-29 19:47

    As others have noted, the general modulus operation requires a division to be done. In some cases, the division can be replaced (by the compiler) by a multiplication. But both can be slow compared to addition/subtraction. Hence, the best performance can be expected by something along these lines:

    long progressCheck = 50000;
    
    long counter = progressCheck;
    
    for (long i = startNum; i <= stopNum; i++){
        if (--counter == 0) {
            System.out.println(i);
            counter = progressCheck;
        }
    }
    

    (As a minor optmiziation attempt we use a pre-decrement down-counter here because on many architectures comparing to 0 immediately after an arithmetic operation costs exactly 0 instructions/CPU cycles because the ALU's flags are already set appropriately by the preceeding operation. A decent optimizing compiler will, however, do that optimization automatically even if you write if (counter++ == 50000) { ... counter = 0; }.)

    Notice that often you don't really want/need modulus, because you know that your loop counter (i) or whatever is only ever incremented by 1, and you really don't care about the actual remainder the modulus will give you, just see if the incrementing-by-one counter hits some value.

    Another 'trick' is to use power-of-two values/limits, e.g. progressCheck = 1024;. Modulus a power of two can be quickly calculated via bitwise and, i.e. if ( (i & (1024-1)) == 0 ) {...}. This should be pretty fast too, and may on some architectures outperform the explicit counter above.

提交回复
热议问题