Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using != with counter controlled loops

Tags:

java

c++

Last question for today all...I will get back with tomorrow..I have a lot to follow up on...

I am looking in Reilly Java text- talking about counter controlled loop patterns..(does not matter what language..)

The author for counter controlled loops (for, while, etc) and with nesting loops...uses the != for test...Now I realize != is used for certain situations with event controlled loops-like sentinel or EOF type of loops- but to me- using it with a counter controlled loop is a bad idea...very prone to errors..

Examples:

x = 0;
while (x != 100) {
   y = 0;
  while (y != 100) {

   ...
   y++;
 }
  x++;
}

Would it be better to just say..using the other relational operators...

x = 0;
while (x < 100) {   //or even better some defined constant...
   y = 0;
  while (y < 100) {

   ...
   y++;
 }
  x++;
} 

Which from what I have seen is usually the way presented in texts..classes.etc..

Once again- would all you considered this bad- or just a different way of doing it... Thanks...

like image 922
iwanttoprogram Avatar asked Jun 18 '09 18:06

iwanttoprogram


People also ask

What are counter controlled loops?

A counter-controlled loop (or counting loop) is a loop whose repetition is managed by a loop control variable whose value represents a count. Also called a while loop.

When using counter controlled repetition in a while loop what is a common logical error?

A common logic error with counter-controlled repetition is an off-by-one error. For example, if the above condition is changed to counter < 10, the loop would iterate only nine times. The general format of the for statement is. for ( initialization; loopContinuationCondition; increment ) statement.

Can be used for a count controlled loop?

A while loop can be used for a count-controlled loop. Although the while loop can be complicated to write correctly, it is possible to simplify its structure and thus improve its readability.


8 Answers

You want your loop condition to be the exact inverse of the desired post-condition.

i= 0;
while( i != 100 ) {
    i += 1;
}
assert i == 100;

You can trivially see that the loop post-condition exactly matches the loop termination condition. No mysteries.

Further, you can prove from the initial condition and the body that it will reach 100 without "somehow" magically skipping a value.

In the case when you have a really complex loop body, that simple parallel structure is essential.

If you use Weakest Precondition techniques for deriving the loop from the post-condition, the loop condition will be the simple matching condition as shown above.

The i < 100 is a bad idea because your loop could have an incorrect body that incremented the variable badly and still "appeared" to work.

like image 166
S.Lott Avatar answered Oct 01 '22 18:10

S.Lott


I would only use

while (x != 100)

if I wanted the loop to terminate when x was exactly 100. So in the vast majority of cases I would use

while (x < 100)

which is a lot more common for counter controlled loops.

EDIT: On second thought, I would always use for-syntax in a counter-controlled loop, so that example should be

for(int i=0; i < 100; ++i)
like image 33
Bill the Lizard Avatar answered Oct 01 '22 17:10

Bill the Lizard


Using < is more common in Java. Modern C++ uses !=.

!= is more likely to catch errors in your code. In most circumstances this is a good thing. If for some reason the counter has not only reached but gone past the bound (usually on the first iteration), then the body will execute with an illegal value. So long as the body of the loop is not hiding errors, then you'll get an exception. If the body is hiding errors, the loop will execute billions of times and it should be obvious there is a bug.

As an example, an interesting vulnerability was found in the implementation of Adobe Flash last year. A pointer used as array could be caused to be initialised as null. Usually not a problem - the process safely crashes out whenever it is first dereferenced. However, a loop with < was used, allowing the body to never executed which then allows the execution to continue. After that, memory could be written at an attacker specified location. Because the value of null is always 0, the attacker knows exactly which memory locations are being written to. This would not have happened if the loop has used !=.

like image 21
Tom Hawtin - tackline Avatar answered Oct 01 '22 16:10

Tom Hawtin - tackline


as other answers have shown,
while(i < 100) is safe*,
while(i != 100) is precise**.

As an aside, you may want to try while(i++ < 100) or for(i = 0; i < 100; ++i) instead of the simpler while loop you have shown--forgetting to increment the counter at the end of the loop is a real pain. Note that, if i=0, i++ will equal 0, and then increment i for next time, and ++i will increment i and then equal 1, so for while(i++ < 100), the postfix ++ operator is necessary.

Also note, that if i was 0 when it got tested in the condition, then it will be 1 in the loop body (for the while example), so if i is an index for an array or something, and not just keeping track of loop iterations, you'd be better to stick with just a for loop (which increments i after each iteration).


*: safe here meaning less likely to enter an infinite loop. It is also unsafe in that it can hide potential errors, if the loop isn't trivial

**: precise in that if it doesn't do exactly what you expect it to, it will fail, and you will notice. Some other answers have also described how to protect you from errors even more in this kind of loop.

like image 24
Carson Myers Avatar answered Oct 01 '22 18:10

Carson Myers


The main advantage of use "!=" over "<" is that is something is going to fail, it should fail big.

For example, if a bug somewhere caused x to enter the loop set to 110, then x < 100 will never enter the loop --- a fact you might miss in debugging. OTOH, if you use x!=100, it will never exit the loop -- something which could not be missing in debugging.

like image 45
James Curran Avatar answered Oct 01 '22 17:10

James Curran


I don't think < necessarily offers you more protection than !=. If you have a case where i is being incremented in way that is unanticipated by you, you should be throwing an exception, not sweeping it under the rug with a <.

For example, if you're really worried about your while loops messing up, you could do something like this:

x = 0;
while (x != 100) 
{
   assert x >= 0;
   assert x < 100;

   y = 0;
   while (y != 100) 
   {    
     assert y >= 0;
     assert y < 100;

     ...
     y++;
   }
   x++;
}

That way, the moment your loop goes out of bounds, your program dies right away (crash early, crash often) and you know your code is messed up.

like image 45
cdmckay Avatar answered Oct 01 '22 16:10

cdmckay


I suspect this may have something to do with C++ iterators.

If you're using integers or pointers, < has a clearly defined meaning. If you're using C++ iterators in a loop, < may not be defined, or may be hard to calculate.

For example, in running through a list, the C++ way would be:

for(std::list<foo>::const_iterator i = bar.begin(); i != bar.end(); ++i)

and really the only way to see if i is before bar.end() is to increment i indefinitely and see if it's ever equal to bar.end().

There's a considerable amount of value in doing minor things the same way all the time.

like image 42
David Thornley Avatar answered Oct 01 '22 18:10

David Thornley


I believe they are semantically the same, the only difference being with != numbers above 100 would obviously also meet the condition where as the < will prevent any number larger than 100 from making it through.

However in the case given, both operators will result in the same output. Now, if somehow the x and y variables were being acted on outside that code, the "<" would be a better way to make sure there was a cutoff at 100 even if they entered with a value of 90, and were not able to continue at all if they entered with a value of 4000. Obviously, the intent on what you are doing at the time would dictate which operator you chose, there are usually several methods to achieve the same result and not always one "correct" way.

like image 20
kscott Avatar answered Oct 01 '22 17:10

kscott