Search code examples
c++if-statementconditional-statements

Order of Conditions in `if ... else if ... else ...` in C++


I'm trying to figure out how to write the most optimal if ... else if ... else ... statement in C++.

Suppose that we have 3 possible conditions based on some n variable value: n = 0, 0 < n < 100, and n = 100. Let's assume that n = 0 will occur in 1% cases, 0 < n < 10090%, and n = 1009%. Note that if ... else if ... else ... will be executed many times and the value of n will be different each time.

My first assumption was to put conditions in the descending order (the most frequent – first, the least frequent – last) like below. However, the first condition will have 3 boolean expressions. And since the first condition will be always executed (in 100% cases) and it consists of 3 boolean expressions (>, <, and &&), those 3 expressions will be executed in 100% cases. (Maybe there will be some optimization made by a compiler, and it will somehow be reduced to 2 expressions.) The second condition will be executed in 10% cases and the third condition – in 1% cases.

So, given that there will be a 1 000 iterations, there will be 3 100 boolean expressions evaluated (3 000 + 100).

if ((n > 0) && (n < 100)) {  // 3 boolean expressions will be executed in 100% cases.
  ...
} else if (n == 100) {  // 1 additional boolean expression – in 10% cases.
  ...
} else {  // n = 0  // No additional boolean expressions – in 1% cases.
  ...
}

If to change the order of conditions (so that to eliminate the condition with 3 boolean expressions), there will be 1 910 boolean expressions evaluated (1 000 + 910).

if (n == 100) {  // 1 boolean expression will be executed in 100% cases.
  ...
} else if (n == 0) {  // 1 additional boolean expression – in 91% cases.
  ...
} else {  // 0 < n < 100  // No additional boolean expressions – in 90% cases.
  ...
}

Do I understand it right? If no, how to properly optimize the code with if ... else if ... else ... for speed?

Update: Based on the comments, did a test. The first variant gives less lines of the compiled code than the second one. Don't know Assembly language, so I'm not sure whether less lines is better in this case.


Solution

  • One of your counts is off. You say:

    if ((n > 0) && (n < 100)) {  // 3 boolean expressions will be executed in 100% cases.
    

    But (1) && is not a Boolean expression, but an implicit if because it short-circuits the expression, and (2) due to the short-circuiting the second half n < 100 will be executed only 99% of the cases. Only n > 0 will be examined in 100% of the cases.

    Apart from that, you are focusing too much on how frequently conditions are evaluated. This is a secondary concern, because first and foremost do note that it is unavoidable to check two conditionals before the most frequent branch can be entered.

    With this in mind, you can now begin to ask if it is possible to avoid checking one of the two conditions with higher probability. The conditions are n > 0 (false in 1% of cases) and n < 100 (false in 10% of cases). Now, if you check n > 0 first, then you can avoid checking the other in 1% of the cases, but when you check n < 100 first, then you can avoid the other check in 10% of the cases. So, that is what you should do:

    if (n == 100) {  // get 10% of the cases out of the way
      ...
    } else if (n == 0) {  // unavoidable second check after first check failed
      ...
    } else {  // most frequent case needs both checks
      ...
    }
    

    (This assumes that [0 ... 100] are the only values that n can take.)