For developers without formal schooing, understanding bitwise operations (and the binary logic behind them) can be hard to understand. Here’s one way of looking at it.

First, take your binary number and break it down by digits. All leading zeros can be discarded.

So 011010 becomes:

1 1 0 1 0

Then, reading from right to left, starting with 1, double each column:

1 1 0 1 0
16 8 4 2 1

For each column (bit) that has a 0, ignore the value in the second row. For each column that has a 1, add it’s value to the total. So for the above example, you’d add 16 + 8 + 2, for a total of 26. [In JS, AS2 and AS3 you can test this with parseInt(‘01101’, 2)].

That’s pretty much all there is to binary. Now I’ll try to demonstrate how bitwise operations become much easier to understand using this basic model.

First, we’ll look at comparison operators.

Bitwise Comparison

  • Bitwise AND &
  • Bitwise OR |
  • Bitwise NOT ~
  • Bitwise XOR ^

These all use the same basic logic, but make comparison using different conditions, similar to the more commonly-understood operators like == and ||

To use the above model, both operands need to be converted to bitwise, but this is usually not required in your programming logic (which will handle translations internally).

Using any of these operators compares each bit, so again I’ll use a table to demonstrate, and keep the example above (011010) as the base, and compare it to 1101 (which I’ll extend to 001101 for visual representation).

1 1 0 1 0
0 1 1 0 1

When using the AND operator, all bits in both numbers (rows) that are equal to ‘1’ are considered to qualify, and are passed to the result:

1 1 0 1 0
0 1 1 0 1
0 1 0 0 0

Since the only bit that matches both numbers if the second-from-left, the result is 01000:

0 1 0 0 0
16 8 4 2 1

So the only value that’s added is 8. So 01000 is the result, and is represented by the decimal 8.

At this point, we know all the following is true:

  • 011010 == 26
  • 001101 == 13
  • 001000 == 8
  • 011010 & 001101 = 001000
  • 26 & 13 = 8

The other binary comparisons use the same logic, but…

For bitwise NOT (~), only count bits that are both 0.
For bitwise OR (|), count bits that are 1 in either row.
For bitwise XOR (^), count bits that are different.

Bitwise Shifting

Using bitwise shift, you can move a row left or right.

Using the original example (11010):

1 1 0 1 0

You can use bitwise shift left (<<) to shift the contents of the row to the left by the operand on the right. So 11010 << 2 would shift the contents of the row by 2 columns to the lef:

1 1 0 1 0 0 0

Using the model mentioned earlier, we can see that the new value would be 104:

1 1 0 1 0 0 0
64 32 16 8 4 2 1

[Adding the qualifying bits: 64 + 32 + 8 = 104]

Using bitwise shift right, the opposite occurs, dropping digits pushed beyond the last column. 11010 >> 3 would become

1 1

Thus, 11010 >> 3 equals 011 (binary), which has a decimal value of 3.

Another way to understand bitwise shifting is that left shift doubles the left operand a number of times equal to the right operand:

3 << 4 is the same as doubling 3, four times:

  • 3 doubled = 6
  • 6 doubled = 12
  • 12 doubled = 24
  • 24 doubled = 48

So (3 << 4) == 48. Right shifting works the same way, but halves (and rounds down) each time.

Bitwise shift and assignment work just like traditional mathematical assignments (such as +=, -=, *=, /=).