Software Engineering Stack Exchange is a question and answer site for professionals, academics, and students working within the systems development life cycle who care about creating, delivering, and maintaining software responsibly. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I got this idea from this question on stackoverflow.com

The following pattern is common:

final x = 10;//whatever constant value
for(int i = 0; i < Math.floor(Math.sqrt(x)) + 1; i++) {
  //...do something
}

The point I'm trying to make is the conditional statement is something complicated and doesn't change.

Is it better to declare it in the initialization section of the loop, as such?

final x = 10;//whatever constant value
for(int i = 0, j = Math.floor(Math.sqrt(x)) + 1; i < j; i++) {
  //...do something
}

Is this more clear?

What if the conditional expression is simple such as

final x = 10;//whatever constant value
for(int i = 0, j = n*n; i > j; j++) {
  //...do something
}
share|improve this question
10  
Why not just move it to the line before the loop, then you can give it a sensible name too. – jonrsharpe 12 hours ago
    
@jonrsharpe I suppose that's another consideration – Celeritas 12 hours ago
1  
Side note, but i < Math.floor(Math.sqrt(x)) + 1 is probably more clearly written as i <= Math.floor(Math.sqrt(x)). – Mehrdad 8 hours ago
1  
@Mehrdad: They're not equivalent. If x is large in magnitude, Math.floor(Math.sqrt(x))+1 is equal to Math.floor(Math.sqrt(x)). :-) – R.. 5 hours ago
    
@R..: c'mon man -__- – Mehrdad 5 hours ago

A good compiler will generate the same code either way, so if you are going for performance, only make a change if it is in a critical loop and you have actually profiled it and found it makes a difference.

However...

We must not forget that code is primarily a medium of communication between humans, and both your options do not communicate to other humans very well. The first gives the impression that the expression needs to be calculated upon every iteration, and the second being in the initialization section implies it will be updated somewhere inside the loop, where it is really constant throughout.

I would actually prefer it be pulled out above the loop and made final to make that immediately and abundantly clear to anyone reading the code. That's not ideal either because it increases the scope of the variable, but your enclosing function should not contain much more than that loop anyway.

share|improve this answer
1  
+1 for mentioning the compiler optimisation – Bergi 9 hours ago
1  
Once you start including function calls it gets much harder for the compiler to optimise. The compiler would have to have special knowlege that Math.sqrt has no side effects. – Peter Green 6 hours ago
    
@PeterGreen If this is Java, the JVM can figure it out, but it might take a while. – chrylis 3 hours ago

What I'd do is something like this:

void doSomeThings() {
    final x = 10;//whatever constant value
    final limit = Math.floor(Math.sqrt(x)) + 1;
    for(int i = 0; i < limit; i++)             
    {
         //...do something
    }
}

Honestly the only good reason to cram initializing j (now limit) into the loop header is to keep it correctly scoped. All it takes to make that a non issue is a nice tight enclosing scope.

I can appreciate the desire to be fast but don't sacrifice readability without a real good reason.

Sure, the compiler may optimize, initializing multiple vars may be legal, but loops are hard enough to debug as it is. Please be kind to the humans. If this really does turn out to be slowing us down it's nice to understand it enough to fix it.

share|improve this answer
    
Good point. I would assume not to bother with another variable if the expression is something simple, for example for(int i = 0; i < n*n; i++){...} you wouldn't assign n*n to a variable would you? – Celeritas 12 hours ago
    
I would and I have. But not for speed. For readability. Readable code tends to be fast on its own. – CandiedOrange 8 hours ago

As @Karl Bielefeldt's said in his answer, this is usually a non-issue.

However, it was at one time a common issue in C and C++, and a trick came about to side-step the issue without reducing code readability— iterate backwards, down to 0.

final x = 10;//whatever constant value
for(int i = Math.floor(Math.sqrt(x)); i >= 0; i--) {
  //...do something
}

Now the conditional in every iteration is just >= 0 which every compiler will compile into 1 or 2 assembly instructions. Every CPU made in the last few decades should have basic checks like these; doing a quick check on my x64 machine I see this predictably turns into cmpl $0x0, -0x14(%rbp) (long-int-compare value 0 vs. register rbp offsetted -14) and jl 0x100000f59 (jump to the instruction following the loop if the previous comparison was true for “2nd-arg < 1st-arg”).

Note that I removed the + 1 from Math.floor(Math.sqrt(x)) + 1; in order for the math to work out, the starting value should be int i = «iterationCount» - 1. Also worth noting is that your iterator must be signed; unsigned int won't work and will likely compiler-warn.

After programming in C-based languages for ~20 years I now only write reverse-index-iterating loops unless there's a specific reason to forward-index-iterate. In addition to simpler checks in the conditionals, reverse-iteration often also side-steps what would otherwise be troublesome array-mutations-while-iterating.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.