QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: Cobalt on December 10, 2021, 06:31:38 pm

Title: IF THEN issue using AND, I think I'm losing my mind!
Post by: Cobalt on December 10, 2021, 06:31:38 pm
given the following:

Code: QB64: [Select]
  1.  
  2.  P.Mouse_over_R = 16
  3.  P.Mouse_over_B = 15
  4.  'The following IF THEN fails even though both values are TRUE(non 0)
  5.  IF P.Mouse_over_R  AND P.Mouse_over_B THEN
  6.    REM Mouse_Over_Data _MOUSEX, _MOUSEY, P.World_X + P.Mouse_over_R - 1, P.World_Y + P.Mouse_over_B - 1
  7.   ELSE
  8.    _PRINTSTRING (0, 0), STR$(P.Mouse_over_R) + STR$(P.Mouse_over_B), _Display
  9.  
FAILS!

BUT given these values...

Code: QB64: [Select]
  1.  
  2.  P.Mouse_over_R = 9
  3.  P.Mouse_over_B = 7
  4.  'The following IF THEN passes
  5.  IF P.Mouse_over_R  AND P.Mouse_over_B THEN
  6.    REM Mouse_Over_Data _MOUSEX, _MOUSEY, P.World_X + P.Mouse_over_R - 1, P.World_Y + P.Mouse_over_B - 1
  7.   ELSE
  8.    _PRINTSTRING (0, 0), STR$(P.Mouse_over_R) + STR$(P.Mouse_over_B), _Display
  9.   END IF
  10.  
WORKS?

So why? In both scenarios the values are non 0 but one works one doesn't?
Now if I add " > 0" to both checks it works all the time, but why is that needed?
What neuron-connections in my brain have failed and made me forget something about 'AND'?
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: SMcNeill on December 10, 2021, 06:39:51 pm
Remember, AND is a binary operation.

Look at your values in binary:

16 = 10000
15 = 01111

AND those bytes...   you get 0 as a result.

16 AND 15 = 0.  It's a FALSE expression.



And the other value?
9 = 1001
7 = 0111

AND those bytes and you get 0001.

9 AND 7 = 1.   It's a TRUE expression.



What you want is:

IF P.MOR <> 0  AND P.MOB <> 0 THEN...
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: bplus on December 10, 2021, 07:10:49 pm
OR

Code: QB64: [Select]
  1. P.Mouse_over_R = 16
  2. P.Mouse_over_B = 15
  3. 'The following IF THEN fails even though both values are TRUE(non 0)
  4. If P.Mouse_over_R Or P.Mouse_over_B Then
  5.     Print "Or works! for True Eval"; P.Mouse_over_R Or P.Mouse_over_B
  6.     Print "Or works! for False Eval"; P.Mouse_over_R Or P.Mouse_over_B
  7.  
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: SMcNeill on December 10, 2021, 07:16:43 pm
You don't want OR.

16 OR 0 = 16...  Which would make it true, and it's obvious Cobalt only wants it true if BOTH conditions are valid.

Just compare them as being <> 0 and you're good to go without false positives.
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: bplus on December 10, 2021, 07:19:37 pm
OK,

alt AND

If one then
  If the other then
     ' Do what you want when both are checked
  end if
end if

This skips checking the other case if first is already 0.
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: George McGinn on December 10, 2021, 08:09:50 pm
This should also work:

Code: QB64: [Select]
  1. IF P.Mouse_over_R AND NOT P.Mouse_over_B THEN
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: SMcNeill on December 11, 2021, 12:34:02 am
This should also work:

Code: QB64: [Select]
  1. IF P.Mouse_over_R AND NOT P.Mouse_over_B THEN

You guys all need to go back to logic school.  The above will NOT work.

X = 16
Y = 0

IF X AND Y THEN...   

What is wanted is a test for IF both conditions are TRUE THEN....

IF X AND NOT Y THEN...
IF 16 AND NOT 0 THEN
IF 16 AND -1 THEN
IF 16 THEN

Congrats!  You just passed your logic as TRUE, even though the second condition was FALSE.

X = 16
Y = -1

IF X AND NOT Y THEN
IF 16 AND NOT -1 THEN
IF 16 AND 0 THEN
IF 0 THEN

And, here you go again -- two true statements evaluate down to a FALSE decision.

Your program won't work because you simply can't be bothered to type <> 0 into your code.  Instead, you have to try to outsmart it by trying to insert convoluted logic to show that <> 0 is for beginners.

Keep things simple guys.  Either use <> 0, or break that IF into two lines as bplus has illustrated above and remove the AND from the situation completely.

Or else just write a LogicalAND function:

FUNCTION L_And (x , y)
   IF X <> 0 AND Y <> 0 THEN L_And = -1
EXIT FUNCTION

IF L_And(16, 15) THEN...

Look!  I reduced typing, don't have a bunch of those blasphemous <> 0 statements in my code, AND it works as intended!  Life doesn't get any better than that!
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: bplus on December 11, 2021, 12:43:01 am
Well I guess Steve beat me to it.

This should also work:

Code: QB64: [Select]
  1. IF P.Mouse_over_R AND NOT P.Mouse_over_B THEN

No:
Code: QB64: [Select]
  1. For i = -1 To 0
  2.     For j = -1 To 0
  3.         If i Then
  4.             If j Then
  5.                 Print "i and j True"
  6.                 Print "i And Not j = "; (i And Not j)
  7.                 Print
  8.             Else
  9.                 Print "i True j False"
  10.                 Print "i And Not j = "; (i And Not j)
  11.                 Print
  12.             End If
  13.         Else
  14.             If j Then
  15.                 Print "i False j True"
  16.                 Print "i And Not j = "; (i And Not j)
  17.                 Print
  18.             Else
  19.                 Print "i and j False"
  20.                 Print "i And Not j = "; (i And Not j)
  21.                 Print
  22.             End If
  23.         End If
  24.     Next
  25.  
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: Cobalt on December 11, 2021, 01:07:37 am
Thanks Steve, guys.  Sometimes I wonder if I'm experiencing the early onset of Alzheimer's. Guess I'll have to bring it up with DR next time.... if I remember that is....

Yeah both R and B have to be >0 otherwise it causes a Subscript out of range error within the routine Mouse_Over_Data. Which is odd cause the map area is the only place that IF THEN is ran and if R has a value then B has to have one too(in that area, R(ed) represents X value and B(lue) represents Y value), but when I just had an R check anytime you saved or loaded a map it pulled the subscript out of range if the mouse was over the map area. Could have just been an issue of order of operations though. If I would have moved that IF THEN to the top of the loop before the possibility of SAVE or LOAD it might not have happened. The mysteries of the universe that we shall never know!(or care about probably)
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: Qwerkey on December 11, 2021, 10:49:30 am
I should say (and I think that I'm in agreement with Steve, though I'm not sure of that!):

If variables are numbers (16 & 15) in this case, then always use equations:
     as Steve's IF P.MOR <> 0  AND P.MOB <> 0 THEN...
     The Boolean algebra is done after the equations are worked out.

Only use Boolean algebra (ie True or False only) when the variables are strictly Booleans (0 or -1 in QB64), eg:
     IF P%% AND NOT Q%% THEN...

Then you can't go wrong.

Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: SMcNeill on December 11, 2021, 10:51:45 am
I should say (and I think that I'm in agreement with Steve, though I'm not sure of that!):

If variables are numbers (16 & 15) in this case, then always use equations:
     as Steve's IF P.MOR <> 0  AND P.MOB <> 0 THEN...
     The Boolean algebra is done after the equations are worked out.

Only use Boolean algebra (ie True or False only) when the variables are strictly Booleans (0 or -1 in QB64), eg:
     IF P%% AND NOT Q%% THEN...

Then you can't go wrong.

100% in agreement with all you said here.  👍
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: Stuart on December 14, 2021, 05:13:33 am
If the main purpose is to make sure that neither value is zero, instead of this : 
IF P.MOR <> 0  AND P.MOB <> 0 THEN...

wouldn't this work just as well and be more simple, shorter, and faster if it was in a loop?
IF P.MOR * P.MOB THEN...

Just wondering...
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: SMcNeill on December 14, 2021, 07:22:22 am
If the main purpose is to make sure that neither value is zero, instead of this : 
IF P.MOR <> 0  AND P.MOB <> 0 THEN...

wouldn't this work just as well and be more simple, shorter, and faster if it was in a loop?
IF P.MOR * P.MOB THEN...

Just wondering...

It would, with one little -- but vitally important - caveat attached:

BE ALERT OF OVERFLOW VALUES!!  THEY COULD GIVE FALSE RESULTS!!

For example, let's just use an _UNSIGNED _BYTE as an example.

_DEFINE A TO Z AS _UNSIGNED _BYTE
A = 16
B = 16

IF A * B THEN....

Now, A * B = 256.  It's JUST the perfect number that if our IF is bound by unsigned bytes, that it's going to overflow to become 0.  All at once, those two TRUE statements just became an unintended FALSE statement.



Now, with that caveat said, I'd also like to say, "I don't have a clue what variable TYPE an IF statement actually uses for internal calculations."  When we do A * B, is the intermittent result that we compare against 0 an _UNSIGNED _BYTE like the two initial variable types?  Is it a LONG?  A _FLOAT??

Honestly, I don't have a clue.  I know I've dug into the question before in the past, but my poor memory can't supply the answer for me at this exact moment.  All I'm certain of is that IF A * B ends up being the *exact* limit of that variable type + 1, it's going to overflow to become 0.  In 99.998% of all cases, it may be a completely moot issue as that internal value is a LONG and you're multiplying two BYTES together -- which will NEVER overflow -- but I'd prefer not to take a chance on it.  When that rare 0.002% glitch shows up where my code DOES multiple two values together that perfectly hit the overflow value back to 0, I know I'd have a three day marathon of debugging and pulling my poor hair out, looking for the issue.

IF A <> 0 AND B <> 0 THEN....    <--- Never any issues with this, and it's actually quite readable and easy to understand.

IF A * B THEN....   <--- This might run faster and be shorter code, but there's always the chance that SOMETIME, it's going to overflow.  And, I know myself -- when it does, something like this would drive me absolutely insane trying to find it and debug it.  Because, after all, it works perfectly well all the rest of the time!
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: STxAxTIC on December 14, 2021, 07:25:49 am
Just an amateur's point of view passing by here, don't mind me, just that:

Code: QB64: [Select]
  1. IF A <> 0 AND B <> 0 THEN

looks OK in this language, but to dis-ambiguate everything, I would use more parentheses so its easier on the eye and on the brain: (plus this is not ambiguous in any language)

Code: QB64: [Select]
  1. IF ((A <> 0) AND (B <> 0)) THEN

On the other hand, stuff like

Code: QB64: [Select]
  1. IF A * B THEN

is a sentence without a verb. Source code should never make me do the work of filling in hidden meanings.
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: SMcNeill on December 14, 2021, 07:43:03 am
I still think, if folks want LOGICAL comparisons, they really should just write a couple of simple logic functions and then use those:

Code: QB64: [Select]
  1. a = 1
  2. b = 2
  3. Print a And b, __AND(a, b)
  4. Print a Or b, __OR(a, b)
  5.  
  6. 'LOGICAL FUNCTIONS FOR AND/OR
  7. Function __AND (x, y)
  8.     If x <> 0 And y <> 0 Then __AND = -1
  9.  
  10. Function __OR (x, y)
  11.     If x <> 0 Or y <> 0 Then __OR = -1

These only return -1 or 0 values for TRUE or FALSE, and they don't do bit-comparison math on our values.  They just give you the logical return without any regard for the bitwise results QB64 normally gives us.
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: Dimster on December 14, 2021, 09:20:25 am
Hi Steve, is line 4 a typo?
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: SMcNeill on December 14, 2021, 09:22:29 am
Hi Steve, is line 4 a typo?

Aye.  Should've been an __OR there, though it doesn't change the results any this time around.  ;)
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: Dimster on December 14, 2021, 09:55:46 am
At first I was thinking it was not a typo but rather a demonstration of how an "OR" would behave in an "AND" function, effectively creating an "XOR".
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: Stuart on December 14, 2021, 11:49:29 am
Quote
IF A <> 0 AND B <> 0 THEN....    <--- Never any issues with this, and it's actually quite readable and easy to understand.

IF A * B THEN....   <--- This might run faster and be shorter code, but there's always the chance that SOMETIME, it's going to overflow.  And, I know myself -- when it does, something like this would drive me absolutely insane trying to find it and debug it.  Because, after all, it works perfectly well all the rest of the time!

I totally agree, since unsigned variables are possible in QB64.
QB4.5 didn't allow unsigned variables, so it was never an issue back in those days...  (I'm just an old style SCREEN 0 type of programmer.)

Quote
Now, with that caveat said, I'd also like to say, "I don't have a clue what variable TYPE an IF statement actually uses for internal calculations."  When we do A * B, is the intermittent result that we compare against 0 an _UNSIGNED _BYTE like the two initial variable types?  Is it a LONG?  A _FLOAT??

That is a very good question...
It seems like it could cause occasional "unexpected results" depending on what the answer really is.
Back in QB4.5, I'm pretty sure that all internal functions like VAL(num$) would ALWAYS be interpreted as a SIGNED FLOAT.
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: SMcNeill on December 14, 2021, 12:19:30 pm
I totally agree, since unsigned variables are possible in QB64.
QB4.5 didn't allow unsigned variables, so it was never an issue back in those days...  (I'm just an old style SCREEN 0 type of programmer.)

That is a very good question...
It seems like it could cause occasional "unexpected results" depending on what the answer really is.
Back in QB4.5, I'm pretty sure that all internal functions like VAL(num$) would ALWAYS be interpreted as a SIGNED FLOAT.

QB45 didn't allow overflow, so it was never a possibility.  If A * B was greater than the variable limit, you'd get Overflow Error on Line X and the program would terminate.

As for QB64, if My poor memory holds correct, I think our C undercode does a lot of function overloading in math operations.  Integers return INT64 values.  Floating point numbers return via FLOAT values. 

If so, then the main value one would have to watch out for would be the SQR(&HFFFFFFFFFFFFFFFF), or two values that multiplied together equaled that value.  (The highest value an INT64 can hold +1.) 

Like I mentioned, the vast majority of the time, I think it'd be basically impossible to hit that value and glitch out.  The only issue is, as a programmer, my personal experience over the years has taught me that IF there's a chance for something to glitch out, it WILL glitch out eventually.

And glitches like this -- that work hundreds or thousands of times with absolutely no problems whatsoever-- are the ones that are almost impossible to find.  Your brain KNOWS it should work.  Your eyes glaze over and instally rule out a simple A * B as the possible culprit.  You go MAD just looking over the same 500,000 line program over and over and over -- and it's ALWAYS the ridiculously long and complex programs that generate these rare glitches -- until you feel like giving up coding and going back to farming...

So the best solution I've found to prevent these future headaches, for myself, is to just not fall into them to begin with.  ;)
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: OldMoses on December 15, 2021, 07:50:06 am
It explains a lot of what I've noticed in working with QB64 as compared to 4.5. It will handle astonishingly large computations on the fly, and you only have to make sure if you're storing any big numbers, that you use an appropriate variable type.

...and, yes, I've hit the limit a time or two. ;)  When you got it, you can't help but play with it...

QB45 didn't allow overflow, so it was never a possibility.  If A * B was greater than the variable limit, you'd get Overflow Error on Line X and the program would terminate.

As for QB64, if My poor memory holds correct, I think our C undercode does a lot of function overloading in math operations.  Integers return INT64 values.  Floating point numbers return via FLOAT values. 

If so, then the main value one would have to watch out for would be the SQR(&HFFFFFFFFFFFFFFFF), or two values that multiplied together equaled that value.  (The highest value an INT64 can hold +1.) 

Like I mentioned, the vast majority of the time, I think it'd be basically impossible to hit that value and glitch out.  The only issue is, as a programmer, my personal experience over the years has taught me that IF there's a chance for something to glitch out, it WILL glitch out eventually.
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: luke on December 15, 2021, 08:01:28 am
QB45 didn't allow overflow, so it was never a possibility.  If A * B was greater than the variable limit, you'd get Overflow Error on Line X and the program would terminate.
Pedant's note: the QuickBasic interpreter will catch overflow. Compiled programs will not catch the error, and will silently wrap values.
Title: Re: IF THEN issue using AND, I think I'm losing my mind!
Post by: johannhowitzer on December 16, 2021, 01:24:02 am
What I do is put

const true = -1
const false = 0

at the top of every program I write.  And I've always been in the habit of writing if n <> false, instead of just if n.  So I would write

if n <> false and p <> false then

This has saved me countless headaches.