QB64.org Forum
Active Forums => QB64 Discussion => Topic started by: Pete on March 27, 2019, 02:59:20 pm
-
Or.. Bitwise ladies sing this song doodah, doodah...
It's nice to shortcut statements like IF LEN(k$) instead of using IF mykey$ <> "" but if you want to combine statements with AND, you need to careful. For instance, you can write IF INSTR(x$, k$) THEN instead of IF INSTR(x$, k$) <> 0 THEN but if you combine it with another statement and use AND, you will experience different results.
PRINT "The first routine uses AND INSTR(x$, k$) THEN. You'll see 'false' zero, for 2, 4, 6, and 8." PRINT "The second routine starts after 9 is processed. It uses 'INSTR(x$, k$) <> 0 THEN' All numbers will be processed." x$
= "123456789":
LOCATE , , 1, 7, 7 PRINT k$:
PRINT "Checkpoint OK: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) =";
INSTR(x$
, k$
);
"LEN(k$) AND INSTR(x$, k$) =";
LEN(k$
) AND INSTR(x$
, k$
): disp%
= 0 disp% = 0
PRINT k$:
PRINT "Can't Process: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) =";
INSTR(x$
, k$
);
"LEN(k$) AND INSTR(x$, k$) =";
LEN(k$
) AND INSTR(x$
, k$
): disp%
= 0
PRINT k$:
PRINT "Checkpoint OK: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) <> 0 =";
INSTR(x$
, k$
) <> 0;
"LEN(k$) AND INSTR(x$, k$) <> 0 =";
LEN(k$
) AND INSTR(x$
, k$
) <> 0: disp%
= 0 disp% = 0
PRINT k$:
PRINT "Can't Process: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) <> 0 =";
INSTR(x$
, k$
) <> 0;
"LEN(k$) AND INSTR(x$, k$) <> 0 =";
LEN(k$
) AND INSTR(x$
, k$
) <> 0: disp%
= 0
This actually 'bit' me in the ASCII a few years ago. I was wondering why what I knew was a true INSTR() result wasn't being processed correctly. When i noticed I had it in a combined conditional statement, I just added the > 0 part, and of course it worked fine. I just thought I'd share this experience here.
Pete
-
This is explained by AND simply *NOT* being a logical operator in QB64; it's a binary operation.
Try these simple commands:
PRINT 1 AND 3
PRINT 1 AND 2
PRINT 2 AND 3
The results are:
1
0
2
And how does this relate to your coding example, you ask?
If k$ = "2", and x$ = "123456789", then INSTR$(x$,k$) is going to equal 2 -- it's in the second position of the search string...
Now, since k$ = "2", the LEN(k$) = 1...
And your IF condition test is:
IF LEN(k$) AND INSTR(x$, k$) THEN
Which processes as:
IF 1 AND 2 THEN...
And, as we saw above, 1 AND 2 are 0 -- which is what QB64 considers to be a FALSE logical value.
You're using BINARY OPERATIONS and expecting LOGIC-BASED RESULTS -- and as you noticed in your code, that's *NOT* going to work properly for you.
The solution is, as you have already noticed, to transform that AND so that you're comparing logic values (TRUE/FALSE) instead of binary numbers.
INSTR(x$, k$) <> 0 can ONLY give you logic values -- 0 for False, -1 for True.
LEN(k$) <> 0 can ONLY give you logic values -- 0 for False, -1 for True.
You can swap out *EITHER* of those binary numbers to make them logical values, and the program will them work as you intend -- the glitch isn't just something in INSTR()...
For example:
PRINT "The first routine uses AND INSTR(x$, k$) THEN. You'll see 'false' zero, for 2, 4, 6, and 8." PRINT "The second routine starts after 9 is processed. It uses 'INSTR(x$, k$) <> 0 THEN' All numbers will be processed." x$
= "123456789":
LOCATE , , 1, 7, 7 PRINT k$:
PRINT "Checkpoint OK: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) =";
INSTR(x$
, k$
);
"LEN(k$) AND INSTR(x$, k$) =";
LEN(k$
) AND INSTR(x$
, k$
): disp%
= 0 disp% = 0
PRINT k$:
PRINT "Can't Process: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) =";
INSTR(x$
, k$
);
"LEN(k$) AND INSTR(x$, k$) =";
LEN(k$
) AND INSTR(x$
, k$
): disp%
= 0
PRINT:
PRINT "DEMO 2 with AND LEN(k$) <> 0 AND INSTR(x$,k$) THEN": i
= 0:
PRINT PRINT k$:
PRINT "Checkpoint OK: ";
"LEN(k$) <> 0 =";
LEN(k$
) <> 0;
"INSTR(x$, k$) =";
INSTR(x$
, k$
);
"LEN(k$) AND INSTR(x$, k$) <> 0 =";
LEN(k$
) <> 0 AND INSTR(x$
, k$
): disp%
= 0 disp% = 0
PRINT k$:
PRINT "Can't Process: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) <> 0 =";
INSTR(x$
, k$
) <> 0;
"LEN(k$) AND INSTR(x$, k$) <> 0 =";
LEN(k$
) AND INSTR(x$
, k$
) <> 0: disp%
= 0
As another, even simpler, demo of this process in action, take a close look at the code below:
The LEN(x$) is 1. The VAL(x$) is 2.
1 AND 2 is 0... The first comparison is false.
1 <> 0 AND 2 is 2... (It becomes -1 AND 2, which then becomes 2)... The second comparison is true.
1 AND 2 <> 0 is 1... (It become 1 AND -1, which then becomes 1)... The third comparison is true.
This isn't a glitch at all with INSTR. It's simply how AND behaves when used as a binary operator.
If you want to avoid these type of issues, be certain to ONLY use AND when you're comparing TRUE/FALSE type results.
Either that, or else write yourself a LOGIC_AND and use it for the comparisons:
-
'* that > 0 is important as it returns a -1 which ANDed with k returns a nonzero value through some bitwise magical goodness.
k=1
a$="123456789"
'* your code here
OR
k=1
a$="123456789"
'* your code here
both of these will work as expected
-
Coo, that is mind-scrambling for us ordinary mortals. The maxim, then, is always use an equation where a number is concerned; only use True/False for actual Booleans.
ie always use the format: IF LEN(k$) > 0 AND INSTR(x$,k$) > 0 THEN
In fact, where an AND or an OR is used, I always include brackets around the comparisons even though they're not required: IF (LEN(k$) > 0) AND (INSTR(x$,k$) > 0) THEN, just to precisely highlight what things are being evaluated.