In my previous entry, I tried to introduce you to binary numbers and all of their uses. Obviously a single blog entry is not nearly enough to fully explain binary, but I at least tried to summarize the information to the best of my ability.
In this entry, I plan to do the same for bitwise operators. I want to explain briefly what they are, what they do, and why they might be useful to Web developers.
Bitwise operators, to put it simply, allow you to manipulate binary numbers easily. With bitwise operators, you can compare, contrast and adjust binary numbers.
What are bitwise operators?
There are a handful of “bitwise operators” and a handful of “bit shift” operators. The “bitwise operators” are as follows:
- will return the exact opposite of a given binary number. A binary number of 1100 0101 will return the exact opposite: 0011 1010. All switches that were turned on will now be turned off, all switches that were turned off will now be turned on.
- will compare two binary numbers. The returned result will have all switches activated that were activated in either of the numbers. In other words, if you compare 1100 0101 and 1101 1000, the result will be 1101 1101
- XOR (exclusive or)
- will compare two binary numbers. The returned result will have all switches activated that were activated in one or the other of the two numbers. Any switches that were activated in both numbers will be deactivated. In other words, if you compare 1100 0101 and 1101 1000, the result will be 0001 1000.
- will compare two binary numbers. The returned result will have all switches activated that were activated in both numbers. All switches that were activated in only one number will be deactivated. In other words, if you compare 1100 0101 and 1101 1000, the result will be 1100 0000.
The “bit shift” operators are as follows:
- Left Shift
- will move the switches to the left within the binary number. In other words, if you choose to “left shift” 0011 1010 once, the result will be 0111 0100. Zeroes will be appended onto the right side of the number for each shift that occurs. If you left shift once, one zero will be appended to the right. If you left shift twice, two zeroes will be appended, etc.
- Right Shift
- will move the switches to the right within the binary number. Zeroes will be appended to the left of the number for each shift that occurs. Any switches that shift past the “ones” place on the far right side will be dropped from the number completely. For example, if you “right shift” the 0011 1010 twice, the result will be 0000 1110.
How can I use bitwise operators?
There are many ways bitwise operators can be used. It helps if they are defined by explaining what the result will actually be when they are used. The three main operators that you will most likely find use for are the “AND”, “OR” and “XOR”.
You would normally use “AND” (the & symbol in PHP) to check to see if a switch is turned on in a number or not. For instance, if you want to know if the “eight” place in a binary number is turned on, you could do: 8&myNumber. If myNumber is 1010 (or the base-ten number 10), then the comparison will return true. If myNumber is 0111 (or the base-ten number 7), it will return false.
You would normally use “OR” (the | pipe symbol in PHP) to turn on a switch. If you want to make sure that the “eight” place in your binary number is activated, you would simply use a function like 8|myNumber. That way, no matter what “myNumber” is, the fourth switch from the right (the “eight” place) will be turned on. For instance, if myNumber was equal to 6 (or 0110 in binary), then the returned result would be 14 (or 1110 in binary).
You would normally use “XOR” (the carat ^ in PHP) to toggle a switch in your binary number. If the switch is currently turned on, XOR will turn it off. If the switch is currently deactivated, XOR will activate it. Let’s use 8^myNumber as the basis for our example. Now, let’s assume myNumber is 14 (or 1110 in binary). Because the “eight” place is currently turned on in myNumber, it will now be turned off, and the result will be 6 (or 0110 in binary). If you were to use 6 (or 0110 in binary) as myNumber, then, because the “eight” place is not currently activated, it would become activated, returning 14 (or 1110 in binary).
I am not sure why you would use the “NOT” operator, unless you wanted to simultaneously deactivate all switches that were activated and activate all switches that were deactivated. I can’t see a whole lot of use for it in my world, but I’m sure a time will come when I’ll find it useful.
The “Right Shift” and “Left Shift” operators are really simple ways of performing multiplication and division. “Left Shift” will multiply the inputted number by 2 for each shift you perform. For instance, 8<<2 (or 0000 1000 left shift twice in binary) will return 32 (or 0010 0000 in binary).
“Right Shift” will divide the inputted number by 2 for each shift you perform. For instance, 8>>1 (or 0000 1000 right shift once in binary) will return 4 (or 0000 0100 in binary). 8<<2 is logically the same as 8/22. 8>>1 is logically the same as 8*21.
Real life examples
Okay, so now I’ve explained what the operators actually do, but I’m sure you might still be wondering how you can use these things in real life.
Really, they can be used for just about anything where you have a series of questions with only two possible answers. Those answers could be “yes/no”, “true/false”, “1/0”, “male/female”, “apples/oranges” or whatever you want them to be. You simply assign one answer to the numeral 1 and one answer to the numeral 0 (in most cases, 1 will represent “yes” and “true” while 0 will represent “no” and “false” – with the apples and oranges example and the male and female example, you can assign it whichever way you choose).
Now, let’s say you’ve got 10 questions that all have only two possible answers each. You could store a person’s answers to each of those questions separately, but that will use unnecessary space in your database and will use unnecessary resources in your application. Up until now, I have been using a method almost as silly. I have been storing my answers in a single database cell (the way you would with binary numbers), but I’ve been separating each answer with a pipe character (really, I could have used any character I wanted, I simply chose the pipe character). So, my database record for a list of questions would look something like “1|1|0|yes|true|false|0|no|oranges|male”. That uses a lot of extra resources in your application and your database as well.
Instead, you can simply store all of the answers together as a single number (in this case, a 10-bit binary number). My example above (assuming that I’ve assigned 1 to oranges and 1 to male) could be translated to “11 0110 0011”, which would then be stored in your database as the number 867. Doesn’t the number “867” seem to make much more sense, from a resource-usage standpoint, than “1|1|0|yes|true|false|0|no|oranges|male”?
Let’s change the example slightly and say that you are programming a Web-based application in which you want to allow users to set up profiles. Let’s say you have 6 items that the user can turn on and off in their profile. We can use the following as an example:
- Would you like to receive e-mail from us? (1)
- Should a pop up window notify you if you have a message? (2)
- Do you want to password-protect your profile? (4)
- Do you have a picture to associate with your profile? (8)
- Do you want to include a signature on your comments? (16)
- Should you stay persistently logged in? (32)
If you look at the list above, the numbers contained inside the parentheses correspond with positions in a binary number.
Now, say you want to find out if a user wants to have a pop up window notify him when he has a new message. All you need to do is use an “AND” operator. The equation would look something like: 2&$usersettings (where $usersettings is the total of all of the binary switches that were turned on by “true/yes” answers to the questions above). If the result returned from that equation is “true”, then you know the user wants to receive pop up notifications on new messages.
Now, say the user decides to turn that off. All you need to do in that case is use an XOR operator. The equation would look something like: 2^$usersettings. Now, if the “two” place in $usersettings was initially turned on, it will be turned off (so, if $usersettings was equal to 34, 15, 7, 3, 2, 6 or any other number that includes the binary 2, then you would turn off that switch, essentially subtracting 2 from the total). If the “two” switch was initially turned off, it will now be turned on (essentially adding 2 to the total).
Finally, let’s say you want to override any user choice on a particular switch, and you want to ensure that it’s always turned on. To do that, you could use an “OR” operator. To keep with the example we’ve been using, let’s imagine that you always want users to receive pop up notifications of new messages, no matter what they select in their profiles. You could use an equation that looks like: 2|$usersettings. That would automatically enable the 2 switch.
Now, if you want to get really handy, let’s say you want to override all of the user’s choices, and turn on all of the switches. You can do so with a single equation: 63|$usersettings. The number 63 is the highest value you can get in a 6-bit binary number. Basically, the number 63 means that all 6 switches are activated. Therefore, if you use an “OR” statement, the processor will find that each of the 6 switches is activated on at least one side of your comparison operator.
I hope you now see the value of dealing with things using binary and bitwise operators. I wish I could go into more detail, and explain the other operators a little better, but I have really just begun to explore them myself. You can find some more information on Wikipedia if you are interested.