Logical AND (Binary)

dcb

Normally Lost
Local time
Tomorrow, 00:40
Joined
Sep 15, 2009
Messages
529
Hi

Searching through the help file and I cant seem to find how to do this:

I am looking to use a logic AND ie

Decimal number 5 (Binary = 101)

5 AND 1 = True
5 AND 2 = False
5 AND 4 = True

I know this exists somewhere .....
 
My Humble apologies - Think this is the method....

Dim bole As Boolean

bole = (5 And 1)
Debug.Print bole '' Evaluates True
bole = (5 And 2)
Debug.Print bole '' Evaluates False
bole = (5 And 4)
Debug.Print bole '' Evaluates True
 
Curious as to what you are seeking to do.
 
Evaluate enums

EG: (Silly example) - Just to demonstrate...
PHP:
Public Enum dcbEnum
    dcbInsert = 1
    dcbRead = 2
    dcbDelete = 4
    dcbUpdate = 8
End Enum

Public Sub ExampleEnumUse()
    Dim UserOptions As dcbEnum
    Dim UserPermission As Boolean
    
    '' User has these options
    UserOptions = dcbDelete + dcbInsert + dcbUpdate '' 8+4+1 = 13
    Debug.Print "UserOptions = " & UserOptions
    '' User wants to insert
    UserPermission = (13 And 1)
    Debug.Print "Insert = " & UserPermission
    '' User wants to read
    UserPermission = (UserOptions And dcbRead) '' Eval False
    Debug.Print "Read = " & UserPermission
End Sub
 
it wont be quite 5 and 1 = true

the logic uses a boolean AND to compare a bit position, for two byte values as follows

permission = (flag and testbyte) > 0

so a flag of 1001 = 9 (ie the bits at 8 and 1 set) will return

flag and 1 = 1 , therefore true
flag and 2 = 0 , therefore false
flag and 4 = 0 , therefore false
flag and 8 = 8 , therefore true

hope this helps
 
Last edited:
Gemma-

Actually, 5 AND 1 = true because 5 = 00000101 and 1 = 00000001, so the evaluation should resolve to 00000001.
 
banana

this takes advantage of the fact that 0 is false, therefore anything else is true - even though a boolean of true actually resolves to -1 (minus 1)

am i being pedantic?
if you do boolean 13 AND 8, you get 8
so I would use

booleanvalue = 13 AND 8 = 8
RATHER THAN JUST ASSUME that this is the same
booleanvalue = 13 AND 8

this latter is slightly sloppy, isnt it? - it may work in VBA, but depends on a particluar language implementation - whereas the former is always correct.

what if MS decided to change their implementation and treat -1 as true, and anything else as false.
 
I'm so sorry. I had a major brainfart when I said "5 AND 1 = true" when it should be "5 AND 1 = 1" as we may not wanting to test for mere true values (e.g. anything that's nonzero).

Still, I'm not so sure why "booleanvalue = 13 AND 8" is considered to be sloppy?

If I wanted to know whether the flag in 8 position was raised, I would do just that:

Code:
Public Enum MyBitMask
   FirstOption = 1
   SecondOption = 2
   ThirdOption = 4
   FourthOption = 8
End Enum

Private BitMask As Long

If BitMask And FourthOtpion Then
   'The 8 position was flagged
Else
   'It wasn't...
End If

If we had a value that didn't have 8 flag filled, the test would fail. Take 18 for example.

Code:
?18 And 8
0

18 = 00010010
13 = 00001101
 
all i was getting at was if you do a boolean/bitwise 13 AND 8, you get 8

so if you say
msgbox(13 and 8) you get 8 displayed

if you say
msgbox(cbool(13 and 8)) you get TRUE displayed

but what I am suggesting is that this assumes that any non-zero value (in this case 8) corresponds to true - but this need not necessarily be so - a compiler could just as easily say that only the value of minus 1 is true, and anything else is false - in which case cbool(8) would return false

or even that a value of 1 is true, 0 is false and anything else is undefined


but EXPLICTLY testing for

booleanvalue = 13 AND 8 > 0 will definitely assign the correct result for a boolean true irrespective of how the compiler implements boolean true and false, since the expression 13 AND 8 > 0 is a TRUE expression.
 
However ...

-1073741824 And -2147483648

Results in a negative ... so ... probably best to test for the specific value of the mask or <>0 ...

(-1073741824 And -2147483648 <> 0)

Or ...

(-1073741824 And -2147483648 = -2147483648)

Also, since we are dealing with VBA's AND and the code is in VBA, I HIGHLY doubt that MS will deviate from the virtual industry standard that 0 is False, anything else is NOT False (note that I did not say True, since comparison expressions are ultimately implicitly compared to 0).
 
So what we are saying is that:

(15 and 8)=8 would be the prefered syntax

As I am trying to evaluate if the enum is "in" the number and I seem to have generated some interest - any other methods or am I on the right track?

This is what I assume MS are doing for their function tests and using xnor (NOT xor) to eval if 2 of the "same" options have been included where this is not allowed.
 
Well, I personally think "(15 and 8)=8" is a bit on suspenders-and-belts side. For one thing, I don't know of any programming languages that doesn't share in the convention that false = 0 and true = not false (e.g. anything but zero). Maybe there is one somewhere out there but would the code ever end up there? Seem very unlikely to me.

I've only used bitmasking in one of project, using VBA to direct how to generate the output to Excel based on user's option, and I basically did as what I coded: "If 13 And 8 Then..."

Not to say Gemma's proposition is incorrect- his method is much more safer but I feel that requires two evaluations for what a single evaluation was sufficient, IMHO.
 
And on the flip side ... :) ..

I use, and encourage others to use, the "(15 and 8)=8" for safety, readabiliy, AND more options.

Readability:
If we use "15 and 8" most of us don't immediately know which one is the bit mask and which one is the value being masked, and with variable names and constants it may become worse (granted sometimes better), but ultimately the intent of the expression is easier for me to see when done in "long" form.

More options:
If we use a Byte type to store options and limit ourself to 1 option = 1 bit flag, then we limit ourselves to 8 options, but if we allow multiple bits to be used to represent a single option, we have A LOT MORE flexibility. Do take note that MSAccess/DAO sets more than one bit in the .Attributes property of objects to represent a single option.

So I personally like to have code that looks something like this:

Code:
Dim lngUserOptions As Long
 
Const cOption1 = 1
Const cOption2 = 2
Const cOption3 = 3 'Note more than one bit is set
Const cOption4 = 4
 
Select Case True
 
    Case (lngOptions And cOption1) = cOption1
        'Do something
 
    Case (lngOptions And cOption2) = cOption2
        'Do something
 
    Case (lngOptions And cOption3) = cOption3
        'Do something
 
    Case (lngOptions And cOption4) = cOption4
        'Do something
 
End Select

So those are my primary reasons for prefering the "(15 And 8) = 8" syntax. :)
 
I think we need to be very careful how we test things, for example: -

MsgBox (CBool(13 And 8))

Displays True in the English version of Access but might display Waar in the Dutch version, I can’t test it.
But if it did it would blow an SQL string build in VBA.

So we also need to be aware that the word ‘True’ is just the name of a constant and it has the value of -1.
In the above situation it is better not to use the Boolean True but use its numerical value as in: -

Dim MyBoolean As Boolean

MyBoolean = True

MsgBox CInt(MyBoolean)



Its incorrect use can also lead to unexpected results: -
Code:
If 5 And 1 Then
    MsgBox "5 And 1 is true"
End If

If 5 And 1 = True Then

Else
    MsgBox "5 And 1 is not equal to True"
End If
So not everything that is true is equal to True, in fact most things are not.
 
>> So not everything that is true is equal to True <<

Yep ... here is one of my favorite sequences of examples ...

? True = -1
True

? CByte(True)
255

? CByte(-1)
<overflow error raised!! --- but I thought True equals -1?>
 
using a variant - say you wanted a function to return a tri-state ?
Code:
Public Function fTristate(intTest As Integer) As Variant
    '' Tests for 1000 and makes sure 100 is not included or both are missing
    '' False = 100
    '' True = 1000
    '' Err = Either missing or both present
     Dim ret As Variant
     Dim bool As Boolean
     bool = Not (intTest And 8) = 8 Xor (intTest And 4) = 4
     If bool Then
     fTristate = "ERROR: You have either both 4(100) and 8(1000) or neither of them"
     '' Raise Err.Number blah blah blah
     Else
     fTristate = (intTest And 8) = 8
     End If
End Function

In the above the variant type would be a Boolean for true and false
 
>> So not everything that is true is equal to True <<

Yep ... here is one of my favorite sequences of examples ...

? True = -1
True

? CByte(True)
255

? CByte(-1)
<overflow error raised!! --- but I thought True equals -1?>

Access sees Cint(True) as -1
But a Boolean remains a bool no matter what..
Thus
Cbyte(CBool(Cint(True))) = 255
 
And on the flip side ... :) ..

Does that mean I'm on the flop side? ;)

Readability:
If we use "15 and 8" most of us don't immediately know which one is the bit mask and which one is the value being masked, and with variable names and constants it may become worse (granted sometimes better), but ultimately the intent of the expression is easier for me to see when done in "long" form.

Fair enough. However, FWIW- I would never actually do "15 and 8" but rather "BitMask And SomeOption" which I personally think becomes clear which is what.

So I personally like to have code that looks something like this:

Code:
Dim lngUserOptions As Long
 
Const cOption1 = 1
Const cOption2 = 2
Const cOption3 = 3 'Note more than one bit is set
Const cOption4 = 4
 
Select Case True
 
    Case (lngOptions And cOption1) = cOption1
        'Do something
 
    Case (lngOptions And cOption2) = cOption2
        'Do something
 
    Case (lngOptions And cOption3) = cOption3
        'Do something
 
    Case (lngOptions And cOption4) = cOption4
        'Do something
 
End Select

Interesting. In my POV, setting a bitmask to 3 is same thing as setting bitmask to cOption1 and cOption2. I would prefer to do this:

Code:
BitMask = BitMask Or (Option1 + Option2)

which achieves same effect but IMHO, is more clear in what it does. I wouldn't want a programmer to come to my code later on and think Option3 represented a different set of bit and mistakenly set up a situation where Option1 and Option2 should be exclusive but get set anyway because of Option3.

I suppose it could get quite tedious if we needed to set many options at once, so I wouldn't oppose writing a function to quickly add all the options:

Code:
BitMask = BitMask Or GetInitialBitsSet()

...

Public Function GetInitialBitsSet() As Long
    GetInitialBitsSet = Option1+Option2+Option3
End Function

The idea being that I would want to keep my bit structure separate from implementation.
 
using a variant - say you wanted a function to return a tri-state ?
Code:
Public Function fTristate(intTest As Integer) As Variant
    '' Tests for 1000 and makes sure 100 is not included or both are missing
    '' False = 100
    '' True = 1000
    '' Err = Either missing or both present
     Dim ret As Variant
     Dim bool As Boolean
     bool = Not (intTest And 8) = 8 Xor (intTest And 4) = 4
     If bool Then
     fTristate = "ERROR: You have either both 4(100) and 8(1000) or neither of them"
     '' Raise Err.Number blah blah blah
     Else
     fTristate = (intTest And 8) = 8
     End If
End Function

In the above the variant type would be a Boolean for true and false

I'm kind of unclear on why one would want a tri-state boolean since you have a Raise Err which would do a better job of alerting the developer of incorrect setting of the bitmask. Using variant & returning the error as a string when the function would be expecting an integer would be expensive and make the code quite odd.

As an alternative, I suppose one could reserve a bit as "error state" but doing so would convey very little information.
 
I'm kind of unclear on why one would want a tri-state boolean since you have a Raise Err which would do a better job of alerting the developer of incorrect setting of the bitmask. Using variant & returning the error as a string when the function would be expecting an integer would be expensive and make the code quite odd.

As an alternative, I suppose one could reserve a bit as "error state" but doing so would convey very little information.

I suppose a better example is where the MS functions either return a null (together with a error raised sometimes) or ##### (please dont ask me which)
I am speaking out of context of my original post ....
 

Users who are viewing this thread

Back
Top Bottom