|
The
bitwise operators and binary math in general have always been a
mystery to me. If not for studying for the zend certification I
still would probably not care to learn them :) However here I am
and I finally got down the mystery of bits and bytes.
Feel
free to check out my web blog at: http://www.litfuel.net/plush
What
this tutorial will cover:
1.
What are bits and bytes and binary math
2.
PHP's
Bitwise Operators
3.
A simple usecase for why you would want to use bitwise operators
PART
1 Bits, Bytes, and Binary Math
| BINARY MATH INTRODUCTION |
|
The bitwise operators utilize something called Binary Math.
If you already know binary math, skip ahead. Binary math is
a BASE 2 numbering system, where as our normal everyday numbering
system is a BASE 10 system. Think back to elementary school
where we learned numbers this way...
Think of the number 4768. Thats a normal everyday decimal
number.
If you write that out full its 4 THOUSAND, 7 HUNDRED, 6 TENS,
8 ONES
or (4 * 103) + (7 * 102) + (6 * 101)
+ (8 * 100) = 4768
The BASE 2 system has the same concept however it goes by
2's instead of 10s. So you can only have a value of 0 or 1.
Lets look at a binary number
00101101 = (0 * 27) + (0 * 26) + (1
* 25) + (0 * 24) + (1 * 23)
+ (1 * 22) + (0 * 21) + (1 * 20)
= 32 + 8 + 4 + 1 = 45
Wow thats alot of math. Lets break it down piece by piece
starting with the first parentheses.
(0 * 27) which means 0 TIMES 2 to the POWER of
7 or 0 * ( 2 * 2 * 2 * 2 * 2 * 2 * 2) which basically comes
out to 0 * 128 which equals 0 (0 times anything is 0)
so going down our binary number we can see it calculates
like this:
0 - (0 * 128) = 0
0 - (0 * 64) = 0
1 - (1 * 32) = 32
0 - (0 * 16) = 0
1 - (1 * 8) = 8
1 - (1 * 4) = 4
0 - (0 * 2) = 0
1 - (1 * 1) = 1
so add those all up together 32 + 8 + 4 + 1 and you get 45
|
What
is a bit? A bit is a representation of 1 or 0. Basically OFF and
ON. Why do computers use such simple math? Well computers process
with electric current so if the current is over a certain level
the computer considers that to mean ON or 1 and if it is under that
level it is set to OFF or 0.
What
is a byte? A byte is made up of 8 bits and the highest value of
a byte is 255, which would mean every bit is set. We will look at
why a byte's maximum value is 255 in just a second.
What
does a byte look like?
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
That
is a representation of 1 Byte.
The "Place Value" column represents the math we did doing
2 to the power of 7,6,5,4,3,2,1,0
So
if all bits are set and the value = 255 my byte would look like
this
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
| |
1
|
1
|
1
|
1
|
1
|
1
|
1
|
1
|
=
|
255 |
How do we get 255?
Lets take it right to left and add up all those values together
1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 = 255
What would the number 22 look like?
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
| |
0
|
0
|
0
|
1
|
0
|
1
|
1
|
0
|
=
|
22
|
2 + 4 + 16 = 22
Lets look at some other examples of decimal to binary, the ones
on the end try for yourself.
43 = 00101011
4 = 00000100
230 = ?
65 = ?
31 = ?
PART
II PHP'S BITWISE OPERATORS
You
can find complete detail on the PHP bitwise operators here: http://www.php.net/manual/en/language.operators.bitwise.php
What are going to cover?
We're going to cover the bitwise operators below and see how they
work
| Example |
Name |
Result |
| $a & $b |
And |
Bits that are set in both $a and $b are set. |
| $a | $b |
Or |
Bits that are set in either $a or $b are set. |
| $a ^ $b |
Xor |
Bits that are set in $a or $b but not both are set. |
| ~ $a |
Not |
Bits that are set in $a are not set, and vice versa. |
| $a << $b |
Shift left |
Shift the bits of $a $b steps to the left (each step means "multiply by
two") |
| $a >> $b |
Shift right |
Shift the bits of $a $b steps to the right (each step means "divide by
two") |
Lets use two variables to get started with the "And" operator
&.
The & or "And" operator takes two values and returns
a decimal version of the binary values the left and right variable
share. So using our tables above we can see that the only bit these
two share is in the 8 position so $a & $b = 8.
| $a
= |
9; |
| $b
= |
10; |
| echo
$a & $b; |
|
This would output the number 8. Why?? Well lets see using our table
example
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
| $a |
0
|
0
|
0
|
0
|
1
|
0
|
0
|
1
|
=
|
9
|
| $b |
0
|
0
|
0
|
0
|
1
|
0
|
1
|
0
|
=
|
10
|
So you can see from the table the only bit they share together
is the 8 bit. So 8 gets returned.. not too hard eh? Lets look at
another example of the & operator.
| $a
= |
36; |
| $b
= |
103; |
| echo
$a & $b; |
|
This would output the number 36. Why?? Well lets see using our
table example again
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
| $a |
0
|
0
|
1
|
0
|
0
|
1
|
0
|
0
|
=
|
36
|
| $b |
0
|
1
|
1
|
0
|
0
|
1
|
1
|
1
|
=
|
103
|
So you can see the only bits these two share together are the bits
32 and 4 which when added together return 36. This operator is saying
"I want to know what bits you both have set in the same column"
Lets move on to the | also known as the "OR" operator.
| $a
= |
9; |
| $b
= |
10; |
| echo
$a | $b; |
|
This would output the number 11. Why?? Well lets see using our
table example
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
| $a |
0
|
0
|
0
|
0
|
1
|
0
|
0
|
1
|
=
|
9
|
| $b |
0
|
0
|
0
|
0
|
1
|
0
|
1
|
0
|
=
|
10
|
If you notice we have 3 bits set, in the 8, 2, and 1 column.. add
those up 8+2+1 and you get 11. It is just saying "I want to
know what bits either one of you guys have set".
Moving on to the ^ operator also known as the "Xor" operator.
| $a
= |
9; |
| $b
= |
10; |
| echo
$a ^ $b; |
|
This would output the number 3. Why?? Well lets see using our table
example
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
| $a |
0
|
0
|
0
|
0
|
1
|
0
|
0
|
1
|
=
|
9
|
| $b |
0
|
0
|
0
|
0
|
1
|
0
|
1
|
0
|
=
|
10
|
The XOR operator wants to know "Tell me what bits you both
have set but I dont want any bits you share" Notice we have
3 bits set but both $a and $b share the 8 bit, we dont want that
one, we just want the 2 bit and the 1 bit that they each have set
but don't share. Soooo 2+1 = 3
OK, here is one that gets tricky the ~ operator also known as the
"NOT" operator.
| $a
= |
9; |
| $b
= |
10; |
| echo
$a & ~$b; |
|
This would output the number 1. Why?? Well lets see using our table
example
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
| $a |
0
|
0
|
0
|
0
|
1
|
0
|
0
|
1
|
=
|
9
|
| $b |
0
|
0
|
0
|
0
|
1
|
0
|
1
|
0
|
=
|
10
|
The NOT operator wants to know what is set in $a but NOT set in
$b because we marked $b with the ~operator in front of it. So looking
at our table we can see the only bit set in $a thats not in $b is
1.
What happens if we do this...
| $a
= |
9; |
| $b
= |
10; |
| echo
~$a & $b; |
|
We get the value 2, because we want the bits set in $b but NOT
set in $a this time, so since they both share the 8 bit, 2 bit is
the only one $b has that $a does not.
BIT SHIFTING TIME!!!
This would output the number 64. Why?? Well lets see using our
table example
|
1
Byte ( 8 bits )
|
| Place
Value |
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
|
|
| $a - BEFORE! |
0
|
0
|
0
|
1
|
0
|
0
|
0
|
0
|
=
|
16
|
| $a - AFTER! |
0
|
1
|
0
|
0
|
0
|
0
|
0
|
0
|
=
|
64
|
How do we get 64? well bit shifting tells PHP to take the variable
$a which in our case is 16 and shift if 2 bits which is basically
like saying take 16 and multiply it by 2 twice. So 16 X 2 = 32 x
2 = 64
So what useful things can you do with the bitwise operations?
Here is a VERY simple and watered down user persmissions system.
This is great if you have many classes of persmission for users
for example...
a user can...
read articles
write articles
edit articles
be an local Administrator
be a global Administrator
So you can setup your permission rules like this in your configuration
file
<?php $read = 1; $write = 2; $readwrite = 16; $local_admin = 32; $global_admin = 64; $jim = 96; $mike = 16; echo "Is Mike Allowed to edit? he has an access level of 16<BR>"; if($mike & 32) { echo 'YES MIKE CAN EDIT'; } else { } echo "<BR><BR>Is Jim Allowed to edit? he has an access level of 96<BR>"; if($jim & 32) { } else { } ?>
|
|
When you run that code you'll see
Is Mike Allowed to edit? he has an access level of 16
NO HE CANNOT
Is Jim Allowed to edit? he has an access level of 32
YES JIM CAN EDIT
Using the AND operator we can clearly see if Mike has the 32 bit
set that is required for this local admin operation, not only is
Jim a local admin but he's also a global admin with the 64 and 32
bit set giving him a 96 permission level. Imagine if you had 20
different levels of access in your application, being able to store
all those in a single integer is VERY handy instead of having to
do something like
if(is_local_admin && is_global_admin && can_edit_articles
&& can_view_articles) etc.... that could get long, ugly
and hard to manage.
Thats about all I have time for at the moment, but I hope to add
more useful things you can do with bitwise operators in the future.
If you have any questions feel free to email me at jplush76@gmail.com
here is a binary cartoon to help you out :) Bitwise ownzors
|