AS3: Bitwise Operations
-----------------
AS3: Main
-----------------
What are bitwise operations?
They are operations that are performed on the bits of a given value. Typically bitwise operations are used with integers. Throughout this tutorial I will only use integers in my examples.
What are the bitwise operators?
They are: ~, |, &, ^, >>, >>>, and <<. Here is a brief explanation of most of them:
~ (Bitwise Compliment)
The ~ operator "flips" each bit. That is, in any given value, all "0"s will become "1", and all "1"s will become "0".
Using this operator you can find the maximum possible value of the uint type:
var uint_max:uint = uint(~0);
This is because the integer value "0" is represented in this manner:
00000000 00000000 00000000 00000000
So when the bitwise compliment is used, every "0" becomes a "1", and every "1" becomes a "0".
Since there are no "1"s, the new value is this:
11111111 11111111 11111111 11111111
Which is precisely the maximum value that a 32-bit unsigned integer can hold.
| (Bitwise OR)
The | operator is very similar to the || operator. The main difference being that | compares bits, and || compares the values that the bits represent.
Let us assume, hypothetically, that in AS3 it is possible to represent a 1-byte integer. With a value of "64" it would look like this:
01000000
Now, assume we have another 1-byte value that is equal to "32". It would look like this:
00100000
If you were to perform a bitwise OR on the two values, like so 64 | 32, this is what happens:
64 | 32 equals:
01000000 (64)
00100000 (32)
-----------------
01100000 (96)
The bitwise OR compares each bit. If either bit is "1" the new bit is also "1". So you can think of it this way:
0 + 0 = 0
1 + 0 = 1
0 + 1 = 1
1 + 1 = 1
& (Bitwise AND)
The & operator, just like the | operator, is similar to the && operator, respectively.
The difference between bitwise OR and bitwise AND is that the AND operator requires both bits to be "1" in order for the new bit to be "1" as well.
You can think of it like this:
0 + 0 = 0
1 + 0 = 0
0 + 1 = 0
1 + 1 = 1
So, using the same two 1-byte integers as above, 64 and 32, you will receive a very different result:
64 & 32 equals:
01000000 (64)
00100000 (32)
-----------------
00000000 (0)
^ (Bitwise Exclusive OR)
The bitwise exlcusive OR operator is kind of like the | and & operator combined.
It functions in this manner:
0 + 0 = 0
1 + 0 = 1
0 + 1 = 1
1 + 1 = 0
In other words: one, or the other, but not both..
Using the same two 1-byte integer values above, you will get these results:
64 ^ 32 equals:
01000000 (64)
00100000 (32)
-----------------
01100000 (96)
In this case it is identical to using the bitwise OR, as there are no two matching "1" bit values.
But lets take a look at two different values:
213 ^ 137
11010101 (213)
10001001 (137)
-----------------
01011100 (92)
Number Systems and Bitshifting
Before explaining how bitshifting works, I must ensure that you have an understanding of how number systems work.
Understanding the difference between binary, octal, decimal, and hexadecimal will make understanding bitshifting a sinch.
First: What exactly is binary?.
Binary is a base2 number system. This means that each decimal point can only represent two differnet values: 0 or 1.
This is very differnet from the number system that you know and love, which is base10.
A base10 number system works like this: take the number "11738" for example.
11738
10000 1000 100 10 1
1 1 7 3 8
11738 means: (One 10,000) + (One 1,000) + (Seven 100s) + (Three 10s) + (Eight 1s).
Now, to make the math a little easier, lets take a look at a smaller value in binary.
Here is what 195 looks like:
11000011
128 64 32 16 8 4 2 1
1 1 0 0 0 0 1 1
11000011 means: (One 128) + (One 64) + (Zero 32s) + (Zero 16s) + (Zero 8s) + (Zero 4s) + (One 2) + (One 1).
Look fimiliar?
Let's take a look at a third, and final, example using hexadecimal. That crazy number system with the letters.
Let's take the number 61,804:
0x5F16C
65536 4096 256 16 1
5 F 1 6 C
0x5F16C means: (Five 65536s, F(15) 4096s, One 256, Six 16s, C(12) 1s).
Now you may be wondering how those 1-10000, 1-128, and 1-65536 ranges are calculated.
It is very simple:
The value of each decimal place is equal to the product of the previous value and the base, with the exception of the first decimal place, which is always "1".
In other words: in base10 the values increment 1..10..100..1000 because each value is being multiplied by the base, which is "10".
In binary the values increment 1..2..4..8 because each value is multiplied by the base, which is "2".
In hexadecimal the values increment 1..16..256..4096 because, you guessed it, the value is mutliplied by the base, which is "16".
If you are reading this section then I assume you now have a solid understanding of how number systems work.
So, let's take a look at what bitshifting is all about.
>> (Right Bitshift)
The >> operator "shifts" bits to the right. It is difficult to adequately explain what this means without just using numbers.
Consider the following:
213 >> 2 equals:
Step 1) 11010101 (213) (initial value)
Step 2) 01101010 (106) (first shift)
Step 3) 00110101 (53) (second shift)
The bits get shifted to the right. Any bits that fall off the right end are lost. A zero is always padded onto the left.
Bitshifting is the binary equivalent of dividing. Each right bit shift is the equivalent of dividing by two (because binary is base2, remember?).
>>> (Logical Right Bitshift)
The >>> operator is almost identical to the >> operator. The only difference is that the >>> operator will preserve the "sign" of the value. That is, whether the value is negative or positive. This is useful when working with unsigned integers and you do not want the value to overflow into a negative value.
<< (Left Bitshift)
The << operator is pretty much the opposite of the >> operator.
The >> operator is the equivalent of dividing by two, and the << operator is the equivalent of multiplying by two.
Consider the following:
213 << 2 equals:
Step 1) 11010101 (213) (initial value)
Step 2) 10101010 (170) (first shift)
Step 3) 01010100 (84) (second shift)
Wait a second. That didn't multiply by two at all!
That is because the integer is a 1-byte value, which I have been using to make the example simper.
In AS3 an integer value is 4-bytes. So lets look at what would actually happen in AS3:
213 << 2 equals:
Step 1) 00000000 00000000 00000000 11010101 (213) (initial value)
Step 2) 00000000 00000000 00000001 10101010 (426) (first shift)
Step 3) 00000000 00000000 00000011 01010100 (852) (second shift)
All bits get shifted to the left, and zeros are padded onto the right.
Continued in next post...
Since bitshifting is in the "left direction" there is no <<< operator. That only exists for right bitshifts.