Pages: [1] 2   Go Down
Author Topic: Strange logic error with a while loop  (Read 558 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I have another strange error (again!)!!
I have an array of longs and I have to find two numbers: 1170000000 or 1180000000.
When I found one of these two numbers (the first or the second, it's the same) I have to break the loop.
I wrote
Code:
while (instr[EIP] != 1170000000 || instr[EIP] != 118000000)
  EIP++;
But it continues after it has found the numbers. I put a serial.print instruction just after the while declaration to print all the numbers it find and I found 1170000000! It is a strange comportament!
I'm very confused...

Thanks for your help!
Jymmy097
Logged

Offline Offline
Edison Member
*
Karma: 18
Posts: 1170
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Put an L after the constant to signify it is long:  117000000L
Logged

Tulsa, OK
Offline Offline
Full Member
***
Karma: 1
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Your logic is wrong, change || to &&.

Essentially you have an infinite loop because the variable cannot simultaneously be both of those numbers. Your current logic says, "if either of those conditions is fulfilled, the loop will continue", whereas you think it says, "if either of those conditions is NOT fulfilled, the loop will NOT continue." Both conditions would have to be fulfilled to break the loop. Change || to && and your problem is solved. New logic says, "Both of these conditions must be fulfilled or else the loop will break."
« Last Edit: July 26, 2013, 11:27:14 am by cypherrage » Logged

Cincinnati, OH
Offline Offline
Sr. Member
****
Karma: 16
Posts: 466
I'm not bossy...I just know what you should be doing.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The way the code's written:

Code:
while (instr[EIP] != 1170000000 || instr[EIP] != 118000000)
  EIP++;

If the current value of the array index into instr[] isn't one of those two values to begin with, EIP can't get incremented. Would this work for you?

Code:
while (true) {
   if (nstr[EIP] == 1170000000L || instr[EIP] == 118000000L) {
      break;
   }
   EIP++;
}

Logged

Offline Offline
Edison Member
*
Karma: 18
Posts: 1170
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think so.
if instr[EIP] == one of the numbers the while will be false and the loop will break.

In other words, as long as instr[EIP] does not equal one of the numbers I am looking for, keep looping.
Logged

Cincinnati, OH
Offline Offline
Sr. Member
****
Karma: 16
Posts: 466
I'm not bossy...I just know what you should be doing.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
if instr[EIP] == one of the numbers the while will be false and the loop will break.
The poster says:
Quote
When I found one of these two numbers (the first or the second, it's the same) I have to break the loop.

Sounds to me that's exactly what he's trying to do. What am I missing?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The third solution has worked:
Code:
While (true)
{
if (instr[EIP] == 1170000000 || instr[EIP] == 1180000000)
Break;
EIP++;
}

cyperrage: you're wrong: if I put && instead of || both of the condition have to be fulfilled, only one have to be fulfilled. Anyway: the same variable can't have two different values at the same time.

Thanks a lot!

Jymmy097
Logged

Offline Offline
Edison Member
*
Karma: 18
Posts: 1170
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

cyberrage is right. You need && because for the || to be false and break the loop, *both* have to be false. If only one is true, the || is true.
Logged

Offline Offline
God Member
*****
Karma: 10
Posts: 650
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You want both to be fulfilled in order to keep incrementing.  If either one is fulfilled youwant to stop incrementing.  

So if you find 11700000 then the while loop says while (false or true) since 1170000 doesn't equal 1180000 so the while loop keeps incrementing.  You say you want it to stop incrementing if you get either one of those numbers.  So you should use && in the original code and it will work.  That way it says only keep incrementing if the number is not 1170000 or 1180000.  If it is either one of those numbers then the while condition comes back false and it stops incrementing.  

You're thing if it equals this OR that, but what you've written is if it is NOT equal to this or NOT equal to that.  That's always true, a number can't equal two things at once.  
Logged

Tulsa, OK
Offline Offline
Full Member
***
Karma: 1
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The third solution has worked:
Code:
While (true)
{
if (instr[EIP] == 1170000000 || instr[EIP] == 1180000000)
Break;
EIP++;
}

cyperrage: you're wrong: if I put && instead of || both of the condition have to be fulfilled, only one have to be fulfilled. Anyway: the same variable can't have two different values at the same time.

Thanks a lot!

Jymmy097

Simply put: No.

Loops work based on the following properties:
1) Whenever the logic inside the parentheses is TRUE, the loop continues.
2) Whenever the logic inside the parentheses is FALSE, the loop breaks.

Let me lay out some Logical operator tables for you. (&& = logical AND, || = logical OR)
                          
  A    |     B     |  AND  |   OR
FALSE | FALSE | FALSE | FALSE
FALSE | TRUE  | FALSE | TRUE
TRUE  | FALSE | FALSE | TRUE
TRUE  | TRUE  | TRUE   | TRUE

Right now, you are using OR, therefore, the loop will ONLY break when the FALSE condition comes up, which only happens when both conditions come up false, which is impossible granted your logic. If you use the AND operator, it is obvious to see that when either condition breaks, the loop will break as well.

Also, as stated above, if you change the != to ==, then your logic will work fine, you just have to change either one, != to ==, or || to &&, the logic will be the same regardless, but you must do either one if you want it to be correct.
« Last Edit: July 26, 2013, 12:06:02 pm by cypherrage » Logged

Cincinnati, OH
Offline Offline
Sr. Member
****
Karma: 16
Posts: 466
I'm not bossy...I just know what you should be doing.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Attached is a simple program that demos what I think jymmy097 is trying to do when he says:

Quote
When I found one of these two numbers (the first or the second, it's the same) I have to break the loop.

Code:
unsigned long instr[] = { 0L, 1L, 2L, 3L, 1170000000L, 0L};

void setup() {
  Serial.begin(9600);
}

void loop() {
  int EIP = 0;
 
  while (true) {
     if (instr[EIP] == 1170000000L || instr[EIP] == 118000000L) {
       Serial.print("Match: EIP = ");
       Serial.println(EIP);
        break;
     }
     Serial.print("No match: EIP = ");
     Serial.println(EIP);
     EIP++;
  }
}
Logged

Offline Offline
God Member
*****
Karma: 10
Posts: 650
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's sort of the long way round but yes if you want to use == then you can use OR.  If you want to use != like in the OP then you'd use AND.  And you get simpler code that way.
Logged

London
Offline Offline
Edison Member
*
Karma: 23
Posts: 1062
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

cyperrage: you're wrong: if I put && instead of || both of the condition have to be fulfilled, only one have to be fulfilled. Anyway: the same variable can't have two different values at the same time.

No. Cyperrage is correct.
Lets say your numbers are 117 and 118 for simplicity. With ||...
Input 116. The first condition is true (not 117) and the second condition is true (not 118).
true || true  = true
Input 117. The first condition is false (= 117) and the second condition is true (not 118).
false || true  = true
Input 118. The first condition is true (not 117) and the second condition is false (=118).
true  || false = true
With ANY input the while loop will continue and not exit. For the loop to exit, both inputs would have to be false (equal to both 117 and 118), and as you say, the same variable can't have two different values at the same time.

Now with &&...
Input 116. The first condition is true (not 117) and the second condition is true (not 118).
true && true  = true
Input 117. The first condition is false (=117) and the second condition is true (not 118).
false && true  = false
Input 118. The first condition is true (not 117) and the second condition is false (=118).
true  && false = false
If either input gives a false (equals either 117 or 118) then the while loop will exit.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The third solution has worked:
Code:
While (true)
{
if (instr[EIP] == 1170000000 || instr[EIP] == 1180000000)
Break;
EIP++;
}

cyperrage: you're wrong: if I put && instead of || both of the condition have to be fulfilled, only one have to be fulfilled. Anyway: the same variable can't have two different values at the same time.

You changed != to == which reverses the logic (see first post).

Something can't be green AND blue, that's true, but it can be not green AND not blue (eg. it could be red).

However it is always not green OR not blue (if it is green it is not blue, and if it is blue it is not green).

Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24349
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Google "de Morgan's Laws"
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Pages: [1] 2   Go Up
Jump to: