user12556559
user12556559

Reputation: 53

Trying to avoid if-else statement inside for-loop but the code seems to have some errors

This snippet works just fine.

for (int i = 0; i < 1; i++) // for some other purpose
{
  // some other code

  double** angle = new double* [10];   // for a 2D matrix
  for (int j = 0; j < 10; j++)
  {
     angle[j] = new double [3];

     if (j == 0) 
            angle[j][0] = 2;          // focused on the first column for now
     else 
            angle[j][0] = angle[j-1][0]+3;

     std::cout << angle[j][0] << std::endl;
  }

  for (int i = 0; i < 10; i++)
     delete[] angle[i];
     delete[] angle; 
}

I am trying to not use conditional statement inside the loop. If I replace that with the following line, the code stops working. Please help me understand it.

angle[j][0] = (j == 0) * 2 + (j != 0) * (angle[j-1][0] + 3);

Using g++ -std=c++11 -o out main.cpp; ./out on Ubuntu 16.04 LTS

Upvotes: 5

Views: 341

Answers (3)

Frodyne
Frodyne

Reputation: 3973

As Sahu said, the problem with your combined line is that you take angle[j-1][0] with j==0, which is undefined behavior. This means that combining both if and else parts into a single non-branching statement is not really possible.

Secondly, these two code snippets look different (with the ternary/conditional operator producing fewer lines of C++ code):

    if (x == 1) 
        A = 7;
    else
        A = 13;

versus

    A = (x == 1) ? 7 : 13;

But they compile to exactly the same machine code.

So, how do we fix your problem of not wanting to branch in every single loop iteration?

Since the test/branch variable (j) is also the loop variable and the test is for j == 0, which is also the starting condition, you can do something like this:

double** angle = new double* [10];   // for a 2D matrix

angle[0] = new double[3];  // Prepare the first element
angle[0][0] = 2;

for (int j = 1; j < 10; j++)  // Fill out the rest
{
    angle[j] = new double[3];
    angle[j][0] = angle[j - 1][0] + 3;

    std::cout << angle[j][0] << std::endl;
}

Where the setup for the first element is moved out of the loop, after which the loop can be started at j=1 and only have the else branch in the loop body (with no test, of course).

However, given that branch predictors in modern CPUs are pretty awesome, and your loop hits the if-branch exactly once; on the first loop-iteration, and the else-branch on every following one, I doubt that you will see much difference in the execution times for the two versions. So, I would simply recommend that you pick the version that you find most easy to read and understand.

Upvotes: 2

R Sahu
R Sahu

Reputation: 206567

The line

angle[j][0] = (j == 0) * 2 + (j != 0) * (angle[j-1][0] + 3);

does not work since you access angle[-1] when j is 0. That is a reason for undefined behavior.

Looking at your comment to the other answer, you are apparently looking for using the conditional operator.

angle[j][0] = (j == 0) ? 2 : (angle[j-1][0] + 3);

Upvotes: 2

CinCout
CinCout

Reputation: 9619

You're trying to use the ternary operator, but the syntax is wrong.

Do this:

angle[j][0] = (j == 0) ? 2 : (angle[j-1][0] + 3);

Upvotes: 3

Related Questions