Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / hex

Introduction to numerical bases

3.86/5 (3 votes)
1 Oct 2015CPOL10 min read 10.9K  
In this article I’ll cover the basics of numeric bases by examples on four bases - decimal, binary, hex and octal.

Introduction to numerical bases

 

Introduction (base 10 system)

We all used to count in base 10 (decimal) system - since we got 10 fingers on our hands, so historically - that’s what happened. I suppose if we were evolved with another finger, our convenient numeric base would change accordingly.

Surprisingly, computers don’t have any fingers at all, so it’s not natural for them to count in our base, it could be, but they weren’t made that way (at least not the common ones that you use on a daily basis) - there are many reasons for that, which will not be covered in this article.

Number Base Convention

Number is a mathematical term which can be represented in different bases, however that doesn’t affect the number itself, it's just a way of representing it.

Similarly, the word "Bean" is represented in English and in other languages differently, but this doesn’t change the meaning of the word “Bean”.

Wiki:

https://en.wikipedia.org/wiki/Numerical_digit

When you are working with numbers in different bases, you will need to note explicitly the base of the number to avoid the confusion, since the same graphic symbol can represent a completely different number:

Example for different bases with same graphical digits:

 

11 - in decimal means : 11

11 - in octal  means: 9

11 - in hex means : 17

 

In our daily lives we use base 10 by default, so there is no need to mention the base type.

 

The decimal base

In base 10 (decimal) each numbers’ digit represents a base 10 number from 0 to 9 (10 digits).

  • From now  on, I will use the word index when I am talking about the place of a digit in our number (counting from the right to left), while the first index is 0 (zero based index), for example:

Decimal number 4687(decimal) -

the number “7” on the 0 index in our decimal .

the number “8” on the 1<sup>st</sup> index in our decimal .

the number “6” on the 2<sup>nd</sup> index in our decimal .

the number “4” on the 3<sup>rd</sup> index in our decimal .

 

  • Each digits’ value in a number is a set of the index to the bower of base, times the digit value (if you are confused don’t worry, we’ll examine it by examples…)

 

Let’s split the number 4687(decimal) to its digits:

 

7 represents 7 times 10 in power of 0 = 7 * 10 ^ 0 = 7 * 1 = 7

8 represents 8 times 10 in power of 1 = 8 * 10 ^ 1 = 8 *10 = 80

6 represents 6 times 10 in power of 2 = 6 * 10 ^ 2 = 6 * 100 = 600

4 represents 4 times 10 in power of 3 = 4 * 10 ^ 3 = 4 * 1000 = 4000

 

Result: 4000 + 600 + 80 + 7 = 4687

Counting in base 10 system

If you’ll count to ten (starting from 0) you will get something like this:

0,1,2,3,4,5,6,7,8,9,10

See what happened after we added 1 to 9?

We started counting with one digit - 0, and then each time we added 1 to our number.

As our number became equal to the base value (10) we had an overflow – se we carried 1 to a new index (1nd index) - which makes our number: 1 * 10 + 0 * 0 = 10.

 

Let's continue counting until we set a new index in our decimal:

10,11,12,13,14,15,16,17,18,19,20

Same idea here:  the only difference is, that we already had 1 on our 1st index, so we added 1 to that index until we got to 20 (decimal) - which is the power of our base (20 = base * 2):

20(decimal) = 2 * (10 ^ 1) + 0 * (10 ^ 1)= 20  * 10 + 0 * 10 = 20 + 0 = 20

 

Another example:

If we'll pick up another random decimal number:  12345.

First index range: 0 – 9

Second index range: 10– 19

Third index range: 20– 29

And so on…

 

Let’s take another look at our number, we’ll split it by indexes and configure the actual meaning of the number:

Our number is 12345, let’s split it to indexes:

5 – 1st index, 4 – 2nd index, 3 – 3rd index, 2 – 4th index, 1 – 5th index

 

Now we can calculate the number mathematically:

12345 = (5 * 10^0) + (4 *10^1) + (3 *10 ^2) + (2 *10 ^3) + (1*10 ^4) =

= (5 * 1) + (4 *10) + (3 *100) + (2 *1000) + (1*10 ^10000) = 123245

 

We are so used to decimal numbers that we are doing those calculations automatically, but if you would to remember you first steps in math lessons you’d probably realize that that’s the way you’ve done it.

 

Decimal calculation table
C#
0 = 0 * (10 ^ 0)        
1 = 1 * (10 ^ 0)        
2 = 2 * (10 ^ 0)        
3 = 3 * (10 ^ 0)        
4 = 5 * (10 ^ 0)        
5 = 6 * (10 ^ 0)        
6 = 7 * (10 ^ 0)        
7 = 7 * (10 ^ 0)        
8 = 8 * (10 ^ 0)
9 = 9 * (10 ^ 0)
10 = 0 * (0 ^ 10) + 1 * (10 ^ 1)
11 = 1 * (0 ^ 10) + 1 * (10 ^ 1)
12 = 2 * (0 ^ 10) + 1 * (10 ^ 1)
13 = 3 * (0 ^ 10) + 1 * (10 ^ 1)
14 = 4 * (0 ^ 10) + 1 * (10 ^ 1)
15 = 5 * (0 ^ 10) + 1 * (10 ^ 1)
16 = 6 * (0 ^ 10) + 1 * (10 ^ 1)
17 = 7 * (0 ^ 10) + 1 * (10 ^ 1)
18 = 8 * (0 ^ 10) + 1 * (10 ^ 1)
19 = 9 * (0 ^ 10) + 1 * (10 ^ 1)
20 = 0 * (0 ^ 10) + 2 * (10 ^ 1)

After we covered the decimal base and the base convention, we can move on to other bases.

 

Binary base

Computers are powered by electricity, so in order to communicate with them, we need to translate our (human) data t­o electrical signals.

Electrical signal can be converted to 0’s and 1’s as:

1 – Electricity is on.

0 - Electricity is off.                                   

We can say that 0 is any voltage less than X, and 1 is any voltage above X (2 states). If we would use a decimal number we would need to define a more complex model - since  we need to define 10 states (for each digit).

There were attempts for making decimal computers, and others bases, but eventually the standard became a binary base.

Computer with different numerical bases:

Decimal computer:

https://en.wikipedia.org/wiki/Decimal_computer

Trenary computer:

https://en.wikipedia.org/wiki/Ternary_computer

 

Binary to decimal and vice versa

You can use different techniques, but in my opinion the easiest way to convert decimal to binary (without a calculator’s help) is to simply iterate over the binary indexes and assemble your desired number, as follows:

Lest take a decimal number: 19

First I’ll just enumerate the indexes of binary digits.

x is the digit on the index - in binary case, can be 0 or 1.

0 index = (2^0) * x = 1 * x

1 index = (2^1) * x = 2 * x

2 index = (2^2) * x = 4 * x

3 index = (2^3) * x = 8 * x

4 index = (2^4) * x = 16 * x

5 index = (2^5) * x = 32 * x

 

32 16 8 4 2 0

Now we’ll iterate over the indexes and try to find a number that fits our decimal:

Reminder: our number is 19

You can see that 32 is bigger than our number, so it cannot represent it.

16 is suitable since it’s less than 19, so let’s mark it up: 10000 (binary)

We’re left with:  19 - 16 = 3

Now we need to represent 3 in binary - let's iterate once again with what’s left:

4 2 0

4 is too large… So we’ll pick up 2 - let’s mark it

10010

We’re left with 19 - 16 - 2 = 1 and it’s obviously - 1(binary)

Let’s assemble our marks: 10011

19 (decimal) = 10011(binary)

 

When converting from binary to decimal we use the same principles as we use in decimals:

 

10011 = 1 * (2^ 0) + 1* (2 ^1) + 1 * (2 ^ 4) =1 + 2 + 16 = 19


Binary calculation table            
C#
0    =  0 * (2 ^ 0) = 0 (decimal)
1    =  1 * (2 ^ 0) = 1 (decimal)
10   =  1 * (2 ^ 0) + 0 * (2 ^ 0) = 2 (decimal)
11   =  1 * (2 ^ 0) + 1 * (2 ^ 1) = 3 (deximal)
100  =  0 * (2 ^ 0) + 0 * (2 ^ 1) + 1 * (2 ^ 2) = 4 (decimal)
101  =  1 * (2 ^ 0) + 0 * (2 ^ 1) + 1 * (2 ^ 2) = 5 (decimal)
110  =  0 * (2 ^ 0) + 1 * (2 ^ 1) + 1 * (2 ^ 2) = 6 (decimal)
111  =  1 * (2 ^ 0) + 1 * (2 ^ 1) + 1 * (2 ^ 2) = 7 (decimal)
1000 =  0 * (2 ^ 0) + 0 * (2 ^ 1) + 0 * (2 ^ 2) + 1 * ( 2 ^ 3) = 8 (decimal)
1001 =  1 * (2 ^ 0) + 0 * (2 ^ 1) + 0 * (2 ^ 2) + 1 * ( 2 ^ 3) = 9 (decimal)
1010 =  0 * (2 ^ 0) + 1 * (2 ^ 1) + 0 * (2 ^ 2) + 1 * ( 2 ^ 3) = 10 (decimal)
1011 =  1 * (2 ^ 0) + 1 * (2 ^ 1) + 0 * (2 ^ 2) + 1 * ( 2 ^ 3) = 11 (decimal)
1100 =  0 * (2 ^ 0) + 0 * (2 ^ 1) + 1 * (2 ^ 2) + 1 * ( 2 ^ 3) = 12 (decimal)
1101 =  1 * (2 ^ 0) + 0 * (2 ^ 1) + 1 * (2 ^ 2) + 1 * ( 2 ^ 3) = 13 (decimal)
1110 =  0 * (2 ^ 0) + 1 * (2 ^ 1) + 1 * (2 ^ 2) + 1 * ( 2 ^ 3) = 14 (decimal)
1111 =  1 * (2 ^ 0) + 1 * (2 ^ 1) + 1 * (2 ^ 2) + 1 * ( 2 ^ 3) = 15 (decimal)
10000 = 0 * (2 ^ 0) + 0 * (2 ^ 1) + 0 * (2 ^ 2) + 0 * ( 2 ^ 3) +  1 * ( 2 ^ 4)= 16 (decimal)
10001 = 1 * (2 ^ 0) + 0 * (2 ^ 1) + 0 * (2 ^ 2) + 0 * ( 2 ^ 3) +  1 * ( 2 ^ 4)= 17 (decimal)
10010 = 0 * (2 ^ 0) + 1 * (2 ^ 1) + 0 * (2 ^ 2) + 0 * ( 2 ^ 3) +  1 * ( 2 ^ 4)= 18 (decimal)
10011 = 1 * (2 ^ 0) + 1 * (2 ^ 1) + 0 * (2 ^ 2) + 0 * ( 2 ^ 3) +  1 * ( 2 ^ 4)= 19 (decimal)
10100 = 0 * (2 ^ 0) + 0 * (2 ^ 1) + 1 * (2 ^ 2) + 0 * ( 2 ^ 3) +  1 * ( 2 ^ 4)= 19 (decimal)

Hex (base 16 )

Hexadecimal is a 16 base number - hexa (six) + decimal (ten), which can be used to represent a large binary number in more humanly readable way.

Since it’s base 16, as in binary and decimals, one digit can represent 0 to 15 decimal value.

Numbers larger than 9 (in decimal base) are represented by two digits, in hexadecimal base we write them as characters to avoid confusion.

One Hex digit binary range: 0000 - 1111 (4 bits)

One hex digit decimal range:

0  1  2  3  4  5  6  7  8  9   A   B   C   D   E   F

0  1  2  3  4  5  6  7  8  9  10   11  12  13  14  15

Binary data of 4 bits can be represented only by one Hex character, so if we’ll look at a binary “large” data example:

32 bit binary number: 00010000000100001111000011111011

You can notice that it's not really readable (at least at first glance).

Let’s convert it to hex:

We’ll separate the large binary into a groups of four (since it’s the hex digit range) and for each binary group we’ll assign an appropriate hex digit:

0001 - 1 (hex) - 1 (decimal)

0000 - 0 (hex) - 0 (decimal)

0001 - 1 (hex) - 1 (decimal)

0000 - 0 (hex) - 0 (decimal)

1111 - F (hex) - 15 (decimal)

0000 - 0 (hex) - 0 (decimal)

1111 - F (hex) - 15 (decimal)

1010 - B (hex) - 11 (decimal)

Assembling all our conversions, we get - 1010F0FB (269545723 in decimal)

 

  • Hex numbers are always written with hex prefix - 0x, in our case : 0x1010F0FB

  • Hex numbers are commonly used in computers, whenever working with binaries – use HEX.

 

Hex calculation table
C#
0 = 0 * (16 ^ 0) =  0 (binary) = 0 (decimal)
1 = 1 * (16 ^ 0) = 1 (binary)   = 1 (decimal)
2 = 2 * (16 ^ 0) = 10 (binary)  = 2(decimal)
3 = 3 * (16 ^ 0) = 11 (binary)  = 3(decimal)
4 = 4 * (16 ^ 0) = 100(binary)  = 4(decimal)
5 = 5 * (16 ^ 0) = 101(binary)  = 5(decimal)
6 = 6 * (16 ^ 0) = 110(binary)  = 6 (decimal)
7 = 7 * (16 ^ 0) = 111(binary)  = 7(decimal)
8 = 8 * (16 ^ 0) = 1000(binary) = 8(decimal)
9 = 9 * (16 ^ 0) = 1001(binary) = 9(decimal)
A = 10 * (16 ^ 0) = 1010(binary) = 10(decimal)
B = 11 * (16 ^ 0) = 1011(binary) = 11(decimal)
C = 12 * (16 ^ 0) = 1100(binary) = 12(decimal)
D = 13 * (16 ^ 0) = 1101(binary) = 13(decimal)
E = 14 * (16 ^ 0) = 1110(binary) = 14(decimal)
F = 15 * (16 ^ 0) = 1111(binary) = 15(decimal)
10= 0 * (16 ^ 0) +  1 * (16 ^ 1) = 10000(binary)= 16(decimal)
11= 1 * (16 ^ 0) +  1 * (16 ^ 1) = 10001(binary)= 17(decimal)
12= 2 * (16 ^ 0) +  1 * (16 ^ 1) = 10010(binary)= 18(decimal)
13= 3 * (16 ^ 0) +  1 * (16 ^ 1) = 10011(binary)= 19(decimal)
14= 4 * (16 ^ 0) +  1 * (16 ^ 1) = 10100(binary)= 20(decimal)

 

Octals (base 8 )

Octal is a base 8 numerical system, which uses the digits 0 to 7.

Using octal numbers is an easier way of representing binary numbers.

If you’ll take any binary number and divide it in groups of three you will get groups of numbers that can be easily reinterpreted as decimals:

Example: 100001111001 -> 100 001 111 001 -> 4 1 7 1 = 2169

Octal base can still pop up in some places, but it’s not that common today...

Notice that 8 and 16 are both powers of 2:

2^3 = 8, 2^4 = 16.

That’s why octal binary range is from 000 - 111 and hex is 0000-1111 because adding another index to binary numbers, multiplies its value by 2 , in programing that kind of operation is called binary shifting.

Octals on Wiki:

https://en.wikipedia.org/wiki/Octal

One octal sign decimal range:

0 1 2 3 4 5 6 7

So if we’ll take a decimal number - 192

we can write it as 300 in octal, again with the same principles that we used in our previous hex bases:

300 = 0 * (8^ 0) + 0 * (8^ 1) + 3 * (8 ^2) = 0 * 0 + 0 * 8 + 3 * 64 =  3 * 64 = 192

Octal  calculation table 
C#
0 = 0 * (8 ^ 0) = 0 (binary)  = 0 (decimal)
1 = 1 * (8 ^ 0) = 1 (binary)   = 1 (decimal)
2 = 2 * (8 ^ 0) = 10 (binary)  = 2(decimal)
3 = 3 * (8 ^ 0) = 11 (binary)  = 3(decimal)
4 = 4 * (8 ^ 0) = 100(binary)  = 4(decimal)
5 = 5 * (8 ^ 0) = 101(binary)  = 5(decimal)
6 = 6 * (8 ^ 0) = 110(binary)  = 6 (decimal)
7 = 7 * (8 ^ 0) = 111(binary)  = 7(decimal)   
10 = 0 * (1 ^ 8) + 1 * (1 ^ 8) = 1000(binary) = 8(decimal)
11 = 1 * (1 ^ 8) + 1 * (1 ^ 8) = 1001(binary) = 9(decimal)
12 = 2 * (1 ^ 8) + 1 * (1 ^ 8) = 1010(binary) = 10(decimal)   
13 = 3 * (1 ^ 8) + 1 * (1 ^ 8) = 1011(binary) = 11(decimal)           
14 = 4 * (1 ^ 8) + 1 * (1 ^ 8) = 1100(binary) = 12(decimal)
15 = 5 * (1 ^ 8) + 1 * (1 ^ 8) = 1101(binary) = 13(decimal)           
16 = 6 * (1 ^ 8) + 1 * (1 ^ 8) = 1110(binary) = 14(decimal)           
17 = 7 * (1 ^ 8) + 1 * (1 ^ 8) = 1111(binary) = 15(decimal)
20 = 0 * (1 ^ 8) + 2 * (1 ^ 8) = 10000(binary)= 16(decimal)           
21 = 1 * (1 ^ 8) + 2 * (1 ^ 8) = 10001(binary)= 17(decimal)           
22 = 2 * (1 ^ 8) + 2 * (1 ^ 8) = 10010(binary)= 18(decimal)           
23 = 3 * (1 ^ 8) + 2 * (1 ^ 8) = 10011(binary)= 19(decimal)           
24 = 4 * (1 ^ 8) + 2 * (1 ^ 8) = 10100(binary)= 20(decimal)       
Octal Elaboration

Octal numbers are used in Unix file permissions, for example when you call chmod command you are specifying the permission by octal number:

chmod 754 myfile.temp

That command will change the file named  - “myfile.temp”’ permissions appropriately.

Unix permissions in a nutshell

4 stands for "read",

2 stands for "write",nds for "execute", and

0 stands for "no permission."

 

So, in our case:

7 stands for combination of : 4 +2 + 1 (read, write, and execute)

5 stands for combination of : 4 + 1 (read, execute)

4 stands for 4 (read)

 

There are three groups: World, Group and User. Each octal digit in our chmod command represents the permission for one of them.

1st - user, 2nd - group, 3rd - others(world)

Summary

Converting from one base to another is pretty easy when you understand how numeric bases work, however, 

in programing you’ll probably encounter the hexes more than other bases since it is more common.

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)