Understanding Bitwise Operators (hopefully)

Posted: December 4th, 2009 | Author: Rob Searles | Filed under: PHP, Tutorials | Comments

After the trouble I had with bitwise operators yesterday I found some time to really sit down and get my head properly around them. Let’s dive straight in.

We need to initially define our flags:

define('BASE', 0); // binary 00000000
define('F1', 1);   // binary 00000001
define('F2', 2);   // binary 00000010
define('F3', 4);   // binary 00000100

To start with we have no flags set, so if we set F1 using the following:

$f1_set = BASE + F1; // $f1_set = 1
echo "F1 set = $f1_set\n";

All is well and good, $f1_set = 1 as expected.

However, what if we set F1 again?

$f1_set_twice = $f1_set + F1; // $f1_set_twice = 2 !!! wrong !!!
echo "F1 set twice = $f1_set_twice\n";

As you can see, if we set F1 twice, it effectively “unsets” F1 and sets F2. Not what we were after.

So why is this? Well, it’s kind of obvious and I was being a bit of a muppet for not spotting it yesterday. The reason is pretty simple: 1 + 1 = 2. (I told you it was obvious!)

Clearly this is not what we want, but how can we solve this? By using the bitwise OR. If we change the statements slightly as follows:

$f1_or_set = BASE | F1; // $f1_or_set = 1
echo "F1 OR set = $f1_or_set\n";
 
$f1_or_set_twice = $f1_or_set | F1; // $f1_or_set_twice = 1 - huzzah!
echo "F1 OR set twice = $f1_or_set_twice\n";

As far as “unsetting” the flags if we use my original method we fall (again) into trouble.

$f1_and_f3 = BASE | F1 | F3; // $f1_and_f3 = 5;
$unset_f3 = $f1_and_f3 - F3; // $unset_f3 = 1
echo "Unset F3 = $unset_f3\n";
 
$unset_f1 = $f1_and_f3 - F1; // $unset_f1 = 4;
echo "Unset F1 = $unset_f1\n";

Now, if we try to “unset” F1 twice, we arrive at the problem.

$unset_f1 = $f1_and_f3 - F1; // $unset_f1 = 3;
echo "Unset F1 = $unset_f1\n";

Unsetting F1 twice here effectively turns off F3 and sets F1 and F2 – completely wrong!

Instead, if we use the &~ binary operator mentioned in Jesper’s comment all works as expected. (note: I can’t find mention of this operator in the PHP docs, please someone help me out)

$f1_and_f3 = BASE | F1 | F3; // $f1_and_f3 = 5;
$unset_f3 = $f1_and_f3 &~ F3; // $unset_f3 = 1
echo "Unset F3 = $unset_f3\n";
 
$unset_f1 = $f1_and_f3 &~ F1; // $unset_f1 = 4;
echo "Unset F1 = $unset_f1\n";

Even if we try to “unset” a flag twice, it still has the same results:

$unset_f1 = $f1_and_f3 &~ F1; // $unset_f1 = 4;
echo "Unset F1 = $unset_f1\n";
 
$unset_f1_twice = $unset_f1 &~ F1; // $unset_f1_twice = 4;
echo "Unset F1 twice = $unset_f1_twice\n";

Also in Jesper’s comment and original post was the use of the left shift operator: <<. After playing around with this it seems very simple to use, as follows:

$f1 = 1;    // 00000001
$f2 = 1<<1; // 00000010
$f3 = 1<<2; // 00000100
$f4 = 1<<3; // 00001000

Or to put it another way:

$f1 = 1;      // 00000001
$f2 = $f1<<1; // 00000010
$f3 = $f2<<1; // 00000100
$f4 = $f3<<1; // 00001000

After all this I think I am a little closer to understanding Bitwise operations, hopefully! Tomorrow I’ll have a crack at testing to see if a flag is turned on or not. Until then…


Bitwise Operators used for Flagging Items

Posted: December 2nd, 2009 | Author: Rob Searles | Filed under: PHP, Tutorials | Comments

Update: Thanks to Jesper Noehr of BitBucket fame for pointing out gaping flaws in my post below (see his comment). I strongly advise you disregard all I have said below, because it will get you into a mess, in much the same way it has me. I’m going to sit down when I have a spare 1/2 hour and try to work out exactly what is going on! Many thanks and big kudos to Jesper, I really appreciate the time you took to correct me.


I have always wondered what the point of Bitwise Operators were,to me they seem to belong to a distant past. However, after reading a couple of great blog posts I have at last an understanding of how they can be put to use, and have started playing around with them a bit (ba dum!).

Jesper Noehr has written about using bitwise operators for a flexible permissions scheme within Python  and Jonathan Snook has taken the bitwise concept further creating a great calendar app in Javascript. After reading these I thought I better dive in, and an opportunity came along yesterday when I had to code a flagging system within PHP.

Read the rest of this entry »