views:

6217

answers:

42

If you had to iterate through a loop 7 times, would you use:

for (int i = 0; i < 7; i++)

or:

for (int i = 0; i <= 6; i++)

There are two considerations:

  • performance
  • readability

For performance I'm assuming Java or C#. Does it matter if "less than" or "less than or equal to" is used? If you have insight for a different language, please indicate which.

For readability I'm assuming 0-based arrays.

UPD: My mention of 0-based arrays may have confused things. I'm not talking about iterating through array elements. Just a general loop.

There is a good point below about using a constant to which would explain what this magic number is. So if I had "int NUMBER_OF_THINGS = 7" then "i <= NUMBER_OF_THINGS - 1" would look weird, wouldn't it.

+5  A: 

It makes no effective difference when it comes to performance. Therefore I would use whichever is easier to understand in the context of the problem you are solving.

Phil Wright
+56  A: 

Both of those loops iterate 7 times. I'd say the one with a 7 in it is more readable/clearer, unless you have a really good reason for the other.

Steve Losh
+3  A: 

In Java 1.5 you can just do

for (int i: myArray) {
    ...
}

so for the array case you don't need to worry.

JesperE
+20  A: 

I always use < array.length because it's easier to read than <= array.length-1.

also having < 7 and given that you know it's starting with a 0 index it should be intuitive that the number is the number of iterations.

Omar Kooheji
+3  A: 

I don't think there is a performance difference. The second form is definitely more readable though, you don't have to mentally subtract one to find the last iteration number.

EDIT: I see others disagree. For me personally, I like to see the actual index numbers in the loop structure. Maybe it's because it's more reminiscent of Perl's 0..6 syntax, which I know is equivalent to (0,1,2,3,4,5,6). If I see a 7, I have to check the operator next to it to see that, in fact, index 7 is never reached.

Adam Bellaire
It depends whether you think that "last iteration number" is more important than "number of iterations". With a 0-based API, they will always differ by 1...
Jon Skeet
+5  A: 

I prefer:

for (int i = 0; i < 7; i++)

I think that translates more readily to "iterating through a loop 7 times".

I'm not sure about the performance implications - I suspect any differences would get compiled away.

Dominic Rodger
+178  A: 

The first is more idiomatic. In particular, it indicates (in a 0-based sense) the number of iterations. When using something 1-based (e.g. JDBC, IIRC) I might be tempted to use <=. So:

for (int i=0; i < count; i++) // For 0-based APIs

for (int i=1; i <= count; i++) // For 1-based APIs

I would expect the performance difference to be insignificantly small in real-world code.

Jon Skeet
You're almost guaranteed there won't be a performance difference. Many architectures, like x86, have "jump on less than or equal in last comparison" instructions. The most likely way you'd see a performance difference would be in some sort of interpreted language that was poorly implemented.
Wedge
This answer needs to be accepted.
Robert S.
Would you consider using != instead? I'd say that that most clearly establishes i as a loop counter and nothing else.
yungchin
yungchin: Now thats a nice question! Would U Jon?, or anyone else?
Lakshman Prasad
I wouldn't usually. It's just too unfamiliar. It also risks going into a very, very long loop if someone accidentally increments i during the loop.
Jon Skeet
Generic programming with STL iterators mandates use of !=. It (accidental double incrementing) hasn't been a problem for me. I do agree that for indices < (or > for descending) are more clear and conventional.
wrang-wrang
Indeed - becuase of the STL idiom (as wrang-wrang mentioned), I find myself using `!=` more and more often as a loop terminating test, even when not using iterators. I was a little reluctant at first because of the reservation Jon/Tony the Pony gave, but I haven't found it to be a problem in practice at all.
Michael Burr
Remember, if you loop on an array's Length using <, the JIT optimizes array access (removes bound checks). So it should be faster that using <=. I haven't checked it though
configurator
(I was talking about C#, by the way)
configurator
A: 

I think either are OK, but when you've chosen, stick to one or the other. If you're used to using <=, then try not to use < and vice versa.

I prefer <=, but in situations where you're working with indexes which start at zero, I'd probably try and use <. It's all personal preference though.

seanyboy
+16  A: 

Seen from an optimizing viewpoint it doesn't matter.

Seen from a code style viewpoint I prefer < . Reason:

for ( int i = 0; i < array.size(); i++ )

is so much more readable than

for ( int i = 0; i <= array.size() -1; i++ )

also < gives you the number of iterations straight away.

Another vote for < is that you might prevent a lot of accidental off-by-one mistakes.

erlando
+2  A: 

I agree with the crowd saying that the 7 makes sense in this case, but I would add that in the case where the 6 is important, say you want to make clear you're only acting on objects up to the 6th index, then the <= is better since it makes the 6 easier to see.

tloach
so, i < size as compared to i<=LAST_FILLED_ARRAY_SLOT
chris
+2  A: 

Way back in college, I remember something about these two operations being similar in compute time on the CPU. Of course, we're talking down at the assembly level.

However, if you're talking C# or Java, I really don't think one is going to be a speed boost over the other, The few nanoseconds you gain are most likely not worth any confusion you introduce.

Personally, I would author the code that makes sense from a business implementation standpoint, and make sure it's easy to read.

casademora
+4  A: 

I'd say use the "< 7" version because that's what the majority of people will read - so if people are skim reading your code, they might interpret it wrongly.

I wouldn't worry about whether "<" is quicker than "<=", just go for readability.

If you do want to go for a speed increase, consider the following:

for (int i = 0; i < this->GetCount(); i++)
{
  // Do something
}

To increase performance you can slightly rearrange it to:

const int count = this->GetCount();
for (int i = 0; i < count; ++i)
{
  // Do something
}

Notice the removal of GetCount() from the loop (because that will be queried in every loop) and the change of "i++" to "++i".

Mark Ingram
I like the second one better because it's easier to read but does it really recalculate the this->GetCount() each time? I've been caught by this when changing the this and the count remaind the same forcing me to do a do..while this->GetCount()
osp70
GetCount() would be called every iteration in the first example.It would only be called once in the second example.If you *need* GetCount() to be called everytime then have it in the loop, if you don't try to keep it outside.
Mark Ingram
Yes I did try it out and you are right, my apologies.
osp70
What difference does it make to use ++i over i++?
Rene Saarsoo
A minor speed increase when using ints, but the increase could be larger if you're incrementing your own classes.Basically ++i increments the actual value, then returns the actual value. i++ creates a temp var, increments real var, then returns temp. No var creation is necessary with ++i.
Mark Ingram
A: 

Strictly from a logical point of view, you have to think that < count would be more efficient than <= count for the exact reason that <= will be testing for equality as well.

PintSizedCat
I don't think so, in assembler it boils down to cmp eax, 7 jl LOOP_STARTor cmp eax, 6 jle LOOP_STARTboth need the same amount of cycles.
Treb
<= can be implemented as !( >)
JohnMcG
!(>) is still two instructions, but Treb is correct that JLE and JL both use the same number of clock cycles, so < and <= take the same amount of time.
Jacob
+2  A: 

As a slight aside, when looping through an array or other collection in .Net, I find

foreach (string item in myarray)
    {
        System.Console.WriteLine(item);
    }

to be more readable than the numeric for loop. This of course assumes that the actual counter Int itself isn't used in the loop code. I do not know if there is a performance change.

Rob Allen
This also requires that you not modify the collection size during the loop.
Jeff B
True. Good catch.
Rob Allen
So would For(i = 0, i < myarray.count, i++)
Rob Allen
+1  A: 

There are many good reasons for writing i<7. Having the number 7 in a loop that iterates 7 times is good. The performance is effectively identical. Almost everybody writes i<7. If you're writing for readability, use the form that everyone will recognise instantly.

DJClayworth
+35  A: 

I remember from my days when we did 8086 Assembly at college it was more performant to do:

for (int i = 6; i > -1; i--)

as there was a JNS operation that means Jump if No Sign. Using this meant that there was no memory lookup after each cycle to get the comparison value and no compare either. These days most compilers optimize register usage so the memory thing is no longer important, but you still get an un-required compare.

By the way putting 7 or 6 in your loop is introducing a "magic number". For better readability you should use a constant with an Intent Revealing Name. Like this:

const int NUMBER_OF_CARS = 7;
for (int i = 0; i < NUMBER_OF_CARS; i++)

EDIT: People aren’t getting the assembly thing so a fuller example is obviously required:

If we do for (i = 0; i <= 10; i++) you need to do this:

    mov esi, 0
loopStartLabel:
                ; Do some stuff
    inc esi
                ; Note cmp command on next line
    cmp esi, 10
    jle exitLoopLabel
    jmp loopStartLabel
exitLoopLabel:

If we do for (int i = 10; i > -1; i--) then you can get away with this:

    mov esi, 10
loopStartLabel:
                ; Do some stuff
    dec esi
                ; Note no cmp command on next line
    jns exitLoopLabel
    jmp loopStartLabel
exitLoopLabel:

I just checked and Microsoft's C++ compiler does not do this optimization, but it does if you do:

for (int i = 10; i >= 0; i--) 

So the moral is if you are using Microsoft C++†, and ascending or descending makes no difference, to get a quick loop you should use:

for (int i = 10; i >= 0; i--)

rather than either of these:

for (int i = 10; i > -1; i--)
for (int i = 0; i <= 10; i++)

But frankly getting the readability of "for (int i = 0; i <= 10; i++)" is normally far more important than missing one processor command.

† Other compilers may do different things.

Martin Brown
The "magic number" case nicely illustrates, why it's usually better to use < than <=.
Rene Saarsoo
Another version is "for (int i = 10; i--; )". Some people use "for (int i = 10; i --> 0; )" and pretend that the combination --> means goes to.
Zayenz
+1 for the assembly code
neuro
A: 

I have always preferred:

for ( int count = 7 ; count > 0 ; -- count )
kenny
What's your rationale? I'm genuinely interested.
chris
thats perfectly fine for reverse looping.. if you ever need such a thing
ShoeLace
One reason is at the uP level compare to 0 is fast. Another is that it reads well to me and the count gives me an easy indication of how many more times are left.
kenny
A: 

It should not be difference in perfomance at least with the x86 compilers. JL and JLE works the same time, as soon as I know. And as for redability, using "<7" for an array of seven elements makes sense.

akalenuk
A: 

I follow the first method as that idiom is repeated frequently.

for (int index = 0; index < array.length; i++)

String s = oldString.substring(0, numChars);

etc.

I'm used to the upper bound being excluded, and would prefer to keep it that way unless there is good reason to change it. (example -- 1 based indexing)

chris
A: 

Go for readability first, optimize later (although, quite honestly, I can't imagine any difference that would be noticeable).

Be aware that the 0 -> K form is a C idiom carried over into C# by having arrays be 0 based. Follow the idiom and don't violate the principal of least astonishment.

plinth
+1  A: 

You could also use != instead. That way, you'll get an infinite loop if you make an error in initialization, causing the error to be noticed earlier and any problems it causes to be limitted to getting stuck in the loop (rather than having a problem much later and not finding it.

Brian
+2  A: 

First, don't use 6 or 7.

Better to use:

int numberOfDays = 7;
for (int day = 0; day < numberOfDays ; day++){

}

In this case it's better then using

for (int day = 0; day <= numberOfDays  - 1; day++){

}

Even better (Java / C#):

for(int day = 0; day < dayArray.Length; i++){

}

And even better (C#)

foreach (int day in days){// day : days in Java

}

The reverse loop is indeed faster but since it's harder to read (if not by you by other programmers, it's better to avoid in. Especially in C#, Java...

Carra
+1  A: 

Making a habit of using < will make it consistent for both you and the reader when you are iterating through an array. It will be simpler for everyone to have a standard convention. And if you're using a language with 0-based arrays, then < is the convention.

This almost certainly matters more than any performance difference between < and <=. Aim for functionality and readability first, then optimize.

Another note is that it would be better to be in the habit of doing ++i rather than i++, since fetch and increment requires a temporary and increment and fetch does not. For integers, your compiler will probably optimize the temporary away, but if your iterating type is more complex, it might not be able to.

JohnMcG
+1  A: 

Don't use magic numbers.

Why is it 7? ( or 6 for that matter).

use the correct symbol for the number you want to use...

In which case I think it is better to use

for ( int i = 0; i < array.size(); i++ )
Krakkos
+3  A: 

In C++, I prefer using !=, which is usable with all STL containers. Not all STL container iterators are less-than comparable.

This scares me a little bit just because there is a very slight outside chance that something might iterate the counter over my intended value which then makes this an infinite loop. The chances are remote and easily detected - but the < _feels_ safer.
Rob Allen
If there's a bug like that in your code, it's probably better to crash and burn than to silently continue :-)
This is the right answer: it puts less demand on your iterator and it's more likely to show up if there's an error in your code. The argument for < is short-sighted. Maybe an infinite loop would be bad back in the 70's when you were paying for CPU time. '!=' is less likely to hide a bug.
David Nehme
Looping over iterators is an entirely different case from looping with a counter. != is essential for iterators.
DJClayworth
+1  A: 

The '<' and '<=' operators are exactly the same performance cost.

The '<' operator is a standard and easier to read in a zero-based loop.

Using ++i instead of i++ improves performance in C++, but not in C# - I don't know about Java.

Jeff B
A: 

JeffB: Can you explain why < and <= have the same performance cost?

piers7
Assembly CMP is used by both. Assembly JL (<) or JLE (<=) is used for the branching - and JL and JLE have the *exact same CPU cycle count*. For clock cycle counts, see: http://home.comcast.net/~fbui/intel_j.html#jxx
Jeff B
A: 

I prefer this:

for (int i = 0; i < 7; i++)

However (this is merely a thought), the readability of it might have to do whether or not arrays are 0-based (C#, Java) or 1-based (VB .NET). I say this because when you work with 0-based arrays, you get in a mindset that 0-6 would run 7 times. I think 0-6 is more intuitive than 1-7. Then again, I come from a C++, Java, C# background.

rodey
A: 

For some languages/technologies like .NET using .Size or .Length or size()/length() is a bad idea is it accesses that property each time it iterates, so assigned it to a variable has a slightly less performance hit.

Chris S
+1  A: 

As people have observed, there is no difference in either of the two alternatives you mentioned. Just to confirm this, I did some simple benchmarking in JavaScript.

You can see the results here. What is not clear from this is that if I swap the position of the 1st and 2nd tests, the results for those 2 tests swap, this is clearly a memory issue. However the 3rd test, one where I reverse the order of the iteration is clearly faster.

David Wees
why do you start with i = 1 in the second case?
Eugene Katz
Hrmm, probably a silly mistake? I whipped this up pretty quickly, maybe 15 minutes.
David Wees
+7  A: 

@Chris, Your statement about .Length being costly in .NET is actually untrue and in the case of simple types the exact opposite.

int len = somearray.Length;
for(i = 0; i < len; i++)
{
  somearray[i].something();
}

is actually slower than

for(i = 0; i < somearray.Length; i++)
{
  somearray[i].something();
}

The later is a case that is optimized by the runtime. Since the runtime can guarantee i is a valid index into the array no bounds checks are done. In the former, the runtime can't guarantee that i wasn't modified prior to the loop and forces bounds checks on the array for every index lookup.

Jeff Mc
Nice to know. Thanks for the info!
cvk
+1  A: 

As everybody says, it is customary to use 0-indexed iterators even for things outside of arrays. If everything begins at 0 and ends at n-1, and lower-bounds are always <= and upper-bounds are always <, there's that much less thinking that you have to do when reviewing the code.

ephemient
A: 

The results doesn't make sense.

From a hardware point of view, <= with a loopNuumber-1 will introduce one extra calculation to do loopNumber-1 per iteration. So I assume that < will take less time, if not same amount of time than <=

This only matters if your loop count is dynamic (i.e. array length). In the original example, he was using a fixed constant - which eliminates the subtraction operation.
Jeff B
+2  A: 

This falls directly under the category of "Making Wrong Code Look Wrong".

In zero-based indexing languages, such as Java or C# people are accustomed to variations on the index < count condition. Thus, leveraging this defacto convention would make off-by-one errors more obvious.

Regarding performance: any good compiler worth its memory footprint should render such as a non-issue.

Ryan Delucchi
+2  A: 

Edsger Dijkstra wrote an article on this back in 1982 where he argues for lower <= i < upper:

There is a smallest natural number. Exclusion of the lower bound —as in b) and d)— forces for a subsequence starting at the smallest natural number the lower bound as mentioned into the realm of the unnatural numbers. That is ugly, so for the lower bound we prefer the ≤ as in a) and c). Consider now the subsequences starting at the smallest natural number: inclusion of the upper bound would then force the latter to be unnatural by the time the sequence has shrunk to the empty one. That is ugly, so for the upper bound we prefer < as in a) and d). We conclude that convention a) is to be preferred.

Martijn
A: 

Premature optimization is the root of all evil. Go with readability unless there is a really good reason to worry about < over <=.

cciotti
A: 

No speed difference, but < is more likely to be correct in a language with 0-based arrays. Also, if you want to iterate down instead of up, you can say:

for (i = 7; --i >= 0; ) ...
Mike Dunlavey
A: 

I would argue it should be <.

Why use many words when a few will do. One test is easier to understand then two. Consquently, it is easier to unit test and modify going forward.

Is the difference small? Yes. But why add any complexity when it is not warranted.

Finally, you are not reliant on any optimizer or implementation of an interpreter when the code is optimized to begin with. To quote Einstein, "keep it as simple as possible but no simpler".

Cam Wolff
+1  A: 

Great question. My answer: use type A ('<')

  • You clearly see how many iterations you have (7).
  • The difference between two endpoints is the width of the range
  • Less characters makes it more readable
  • You more often have the total number of elements i < strlen(s) rather than the index of the last element so uniformity is important.

Another problem is with this whole construct. i appears 3 times in it, so it can be mistyped. The for-loop construct says how to do instead of what to do. I suggest adopting this:

BOOST_FOREACH(i, IntegerInterval(0,7))

This is more clear, compiles to exaclty the same asm instructions, etc. Ask me for the code of IntegerInterval if you like.

Pavel Radzivilovsky
A: 

I want to make an answer as accepted. There is no right answer, of course, so I'm creating this placeholder. I wish there was a better way.

Eugene Katz
A: 

When someone uses != or == where he could have used <, <=, >, or >= he conveys a message: "I know what I'm doing here".

Longpoke
A: 

So many answers ... but I believe I have something to add.

My preference is for the literal numbers to clearly show what values "i" will take in the loop. So in the case of iterating though a zero-based array:

for (int i = 0; i <= array.Length - 1; ++i)

And if you're just looping, not iterating through an array, counting from 1 to 7 is pretty intuitive:

for (int i = 1; i <= 7; ++i)

Readability trumps performance until you profile it, as you probably don't know what the compiler or runtime is going to do with your code until then.

Nick Westgate