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<iostream>
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.

Coin Marketplace

STEEM 0.15
TRX 0.12
JST 0.025
BTC 54441.42
ETH 2433.25
USDT 1.00
SBD 2.14