Easy Tutorial: Computer Programming for DUMMIES -- binary, bitwise operators, and 2^n


Image source

Hey guys! This is going to be a fairly simple tutorial. I'm coding in C++, but a lot of this will translate very easily to other languages. If you want to check out my other programming tutorials, here they are:

Part 1: Hello World!

Part 2: Variables

Part 3: Functions

Part 4: if(), else, else if()

Part 5: Loops

Part 6: Arrays

Part 7: Basic Input/Output

Part 9: Sorting Arrays

Part 10: Random Numbers

Part 11: Colored Text in your Terminal

Part 12: Recursion

Part 13: Binary Search

Part 14: 2D Arrays

Part 15: String Processing

This tutorial is about bitwise operators. I will touch on all of the bitwise operators, but I want to focus mostly on the bit shift operators. Before we get started, you need to understand how binary works. Binary is a number system with only 2 numbers (0 and 1). This is commonly used in programming because this is the only number system any computer knows. The 0 and 1 represent on and off signals. You have to remember, computers are just machines. They have no sort of intelligence at all! Here are decimal numbers compared to binary:

1 - 0001
2 - 0010
3 - 0011
4 - 0100
5 - 0101
6 - 0110
7 - 0111
8 - 1000

One way to look at binary is that each digit represents 2 to some power. Take 7 for example:


0 ----- 1 ----- 1 ----- 1
2^3 + 2^2 + 2^1 + 2^0
8(0) + 4(1) + 2(1) + 1(1)


4 + 2 + 1 = 7

&

This is the binary AND operator. It copies a bit if there is one in both operands. Here is what I mean:
0101 & 1110 --> 0100
0000 & 1111 --> 0000
1101 & 0011 --> 0001
The result only has a bit in the place where there was a bit present in BOTH operands.

|

This is the binary OR operator. It copies a bit if there is one in either operands. For example:
0000 | 1110 --> 1110
0101 | 1010 --> 1111
0100 | 0110 --> 0110

^

This is the binary XOR operator. In other words, this is the EXCLUSIVE OR operator. It copies a bit if there is one present in only one or the other, not both. Here are some examples:
0000 ^ 0101 --> 0101
1110 ^ 1111 --> 0001
1111 ^ 1010--> 0101

~

This is the binary "Ones Compliment" operator. This just flips the bits. Here is what I mean by that:
~0101 --> 1010
~1111 --> 0000
~1100 --> 0011

<<

This is the binary left shift operator. It shifts the bits an amount specified by the right operand. Examples:
0110 << 1 --> 1100
0010 << 2 --> 1000
0001 << 3 --> 1000

>>

As you may have guessed, this is the binary right shift operator. It shifts the bits an amount specified by the right operand. Examples:
1100 >> 1 --> 0110
1000 >> 2 --> 0010
1000 >> 3 --> 0001

A deeper look at the bit-shift operators

What does it mean for a variable of type int if you shift its bits? Well to answer that, we have to know what it means to the computer to be an integer. An integer in C++ is 4 bytes. That is 32 bits. What is the largest number type int can support? Well that's simple right? It is just:
11111111 11111111 11111111 11111111 = 4,294,967,295
Wrong! It is actually:
01111111 11111111 11111111 11111111 = 2,147,483,647
Why is this? Remember, type int supports negative numbers. That first bit just indicates whether the integer is positive or negative.

So what if we use bit-shift on an integer? What does that mean? Well let's take a look. Suppose we have the integer 5:
00000000 00000000 00000000 00000101
Let's do a bit-shift.
00000000 00000000 00000000 00000101 << 1 =
00000000 00000000 00000000 00001010 --> This is 10
Let's try it with 2:
00000000 00000000 00000000 00000101 << 2 =
00000000 00000000 00000000 00010100 --> This is 20
And with 3:
00000000 00000000 00000000 00000101 << 3 =
00000000 00000000 00000000 00101000 --> This is 40

When we left bit-shift 1 time, 5 was multiplied by 2.
When we left bit-shift 2 times, 5 was multiplied by 4.
When we left bit-shift 3 times, 5 was multiplied by 8.

Do you notice the pattern?
2 = 2^1
4 = 2^2
8 = 2^3

Bit-shifting an integer left n amount of times is equivalent to multiplying the number by 2^n. This is basically the same idea for right bit-shifts, except instead of multiplying, it is divided.

Here is a program I wrote based on that idea. It easily calculates 2^n for values of n 0-30.

#include
using namespace std;

int main()
{
    cout << "Powers of 2:\n";
    int power = 1;
    for(int x = 0; x < 31; x++)
    {
        cout << "2^" << x << " = "<< power << endl;
        power = power << 1;
    }
    
    return 0;
}

Here is the output:

[cmw4026@omega test]$ g++ bit.cpp
[cmw4026@omega test]$ ./a.out
Powers of 2:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
2^16 = 65536
2^17 = 131072
2^18 = 262144
2^19 = 524288
2^20 = 1048576
2^21 = 2097152
2^22 = 4194304
2^23 = 8388608
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
2^27 = 134217728
2^28 = 268435456
2^29 = 536870912
2^30 = 1073741824
[cmw4026@omega test]$

Note: If I calculated 2^31, the output would look like this:

2^31 = -2147483648

That is because The first bit (that indicates positive or negative) was changed. A way to fix that would be to use unsigned int instead of int.

I hope this was helpful! Leave suggestions in the comments!


On a side note, @dwinblood makes really great game development tutorials using Unity. Here is a link to one of his tutorials. There are more links to the rest of them on that post.

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now