Reputation: 54103
I have a decision tree that uses bit sums to determine branching.
For example: If we have rules: 1,2,4,8,16 the sum is determined by: if true then sum += ruleId.
The branching function, rather than do:
if(sum == 23) =>
else if(sum == 15) =>
Uses a bitwise AND:
if(sum & 23 == 23) =>
else if(sum & 15 == 15) =>
What is the difference between using the bitwise AND and the == ?
What I need to do is generate a List<Tuple<int,boo>>
that will lead a given outcome to evaluate true. My thinking was to do:
For 23, for example:
1 && 2 && 4 && 8 && !16
Will cause it to evaluate to true. However, what impact does the bitwise AND have on this? What do I need to change to correctly output the expression(s) that will lead it to be true?
Upvotes: 0
Views: 121
Reputation: 48415
What is the difference between using the bitwise AND and the == ?
Well ==
checks to see if the two values are equal, simple. Bitwise AND calculates a value where the bits match. When this is combined with the equals check then you are effectively checking if sum
has the same bits set as 23
uses.
Easier to understand if you write the bits down, lets say sum = 31
:
0001 1111 // (sum 31)
& 0001 0111 // (23)
= 0001 0111 // (only set 1 if *both* are 1)
Notice you end up with the same as 23
so when you do (sum & 23) == 23
you get true
. The purpose of this is to check if specific bits are set. In the case of 23
you are checking if bits 16, 4, 2 and 1 are set.
"C# Bit Flags"
is a useful search term if you want to find out more information.
Note, you need to use brackets around the bitwise AND as the order of precedence will try to evaluate the ==
first:
if((sum & 23) == 23)
This is purely guessing at what you might be trying to acheive, but if you are trying to execute each rule that has been set then you might want something like this:
if((sum & 1) == 1)
ExecuteRule1();
if((sum & 2) == 2)
ExecuteRule2();
if((sum & 4) == 4)
ExecuteRule4();
if((sum & 8) == 8)
ExecuteRule8();
if((sum & 16) == 16)
ExecuteRule16();
With this code, in the case of sum = 23
it will execute rules 1, 2, 4 and 16. But will skip rule 8.
Upvotes: 3
Reputation: 5314
Why use bitwise operations at all? In the specific case that you mentioned, it won't matter (as long as you wrap the AND in parens like musefan mentions).
But, what happens if something is slightly different? For example, if a new developer comes along later and has to add a case, and doesn't understand how it works. They add the next bit (32, or 100000) and add their check to the bottom of the if
s:
if((sum & 23) == 23) =>
else if((sum & 15) == 15) =>
//...
else if((sum & 31) == 31) =>
What happens?
Well, 31 in binary & (bitwise AND) 23 in binary:
11111
10111
-----
10111
Uh oh! that evaluates to true! And since they, not knowing any better, added it to the bottom, 23 evaluates to TRUE first and 31 never gets evaluated.
So, it becomes a question of your intention. If that's expected behavior (I doubt it) then you can use bitwise ops, and you'll always know that if you're checking against, for example, 23, you're checking that those specific bits are set, and NOT that they are the only bits set. If you want to know whether ONLY all of the bits in 23 are set, use (sum == 23).
Upvotes: 2
Reputation: 454
You need a further comparison (like ==) when you have multiple bits being selected. Thus
if (sum & 020)
Selects exactly one bit. Either it's on or it's off.
if (sum & 017)
Selects the last four bits, but will evaluate to true if any of those bits are set.
if ((sum & 017) == 017)
Selects the last four bits, and all bits must be set for the expression to be true.
However, none of these tests look at other bits that may be set. If you want to assert that some bits are set and others are not, you get more complicated tests:
if ((sum & 017) == 017 && !(sum & 060))
At some point, you cross over to where it is a clearer expression of your intent to do an equality comparison than a bit mask.
BTW, you will note that I am using octal constants. Octal or decimal are easier to use and maintain for bit masking (IMO).
Upvotes: 0
Reputation: 4700
The equality operator is going to be true only if the sum equals the value that you're testing against. The bitwise && check will make sure that all of the bits represented by that number are set in your value.
For example
sum = 23 (10111), then sum == 23 will be true, as will sum & 23 == 23.
sum = 25 (11001), then sum == 23 will be false, but sum & 23 now returns 17.
11001
& 10111
======
10001 (17)
Upvotes: 0