Lately I’ve been spending a lot of time thinking about my career and where it’s going. I don’t want to give the impression that I have never thought about my career before, but now the thoughts are becoming constant.
Hexadecimal. Binary. Decimal. Byte Arrays. These concepts are inter-related in my opinion. For a programmer, these concepts should not be new. However, I have found that many developers do not understand the inner workings or the structure of these types. These types are the basis of much of the programming world. In order to be proficient (in my opinion) as a developer, it is best to have a foundational knowledge of these types. This post is meant to cover one aspect of these types: numerical bases and hexadecimal. It will give a basic overview of the mathematical background of number bases and then segue into hexadecimal and conversion. A conversion tool is embedded into the post so you can try it out while you learn!
A numerical base is just a symbolic set of symbols to represent a number (normally an integer). We are normally used to seeing numbers represented as base 10 numbers; meaning the numbers in a valid numerical sequence can contain digits 0 through 9. So what does the 10 stand for in "base 10"? It represents the number of valid digits that can be used in a sequence.
There are two other major numerical bases you may have heard of and be used to seeing: Hexadecimal, Binary. Hexadecimal (as its name suggests; Hexadecimal = 16) is base 16 while Binary is base 2. Binary is pretty easy to represent. We naturally choose 0 and 1 as the digits (although theoretically it can be different symbols). Then we have hexadecimal which is base 16.
Well then...we only have 10 digits to work with. How do we extend our symbols to include 6 more? Let's add A, B, C, D, E, F. We can then assign values to these to represent values at different positions.
A = 10, B = 11, C = 12, D = 13, E = 14, F = 15
Awesome! Now we have 3 complete sets of bases we can work with:
Although we're only going to consider these three sets, your base can be anything. The bases don't even have to be rational (including π / pi). However, what these mean and how they're used will not be covered here since their application to general computing is very specialized (see here).
These bases are chosen for a reason. Can you guess which of the three is the least useful to a computer? Yep. You're right. Decimal.
The decimal is used for the express purpose of human readability. But eventually, it will be converted down to a binary representation. This is because 1's and 0's can easily be represented in a processor as voltages. Typically in modern processors 0 is represented as GND (not necessarily 0V but close) and HI (1.3V to 3.3V). So this makes binary the most useful representation. There is a whole area of mathematics dedicated to optimizing boolean algebra and logic (Boolean Algebra).
The next most useful of the three is Hexadecimal. Hex (as it is affectionately coined) is a good representation of groups of bytes. Since their are 16 possiblities per digit, we can show that there are 4 bits that can be assigned to each one. For this reason, more times than not, you will see two Hex digits grouped together to form a byte (8 bits) of information. Since a byte is a fundamental type of most programming languages, we find them a useful tool for bit manipulation and grouping. I am not aware of any processor architectures that are less than 8-bit.
To expand on this idea a bit, we can show that an Integer (32-bit) is 4 bytes (8-bits/byte) and 8 hex digits long. This being a highly used variable type, we will base the rest of the discussion on breaking this type apart.
Note: An integer can also be referred to as a DWORD (Double Word) as coined by Microsoft/Intel.
A final note is about notation. When writing these numbers in different formats, we may want to mix these into the same equation for simplicity so we need to know how to denote these. The number ten (10) can be represented several different ways. To denote a base, simply add a subscript of the base after the number. The number will then be known it is in the base of the subscript value. This is necessary because many bases share many of the same digits.
Below are the ways it can be represented in binary (2), decimal (10), and hexadecimal (16).
It is important to remember that all numerical notations (in the U.S.) has the least significant digit on the right. So the far right digit will always represent the smallest change in a value when altered. Try this out in the converter below to see what I mean.
Note: This tool may not work in all versions of Internet Explorer.
Converting from a representation other than base 10 to base 10 is actually very easy. For an 8-digit base-16 hex number the equation is below:
is the digit in the string. In the case of FFE564BB,
is B and
is the final decimal value.
If you expand this out to binary and use all 32 digits in place of the
variable and replace 16 with 2 then you can convert from binary to decimal as well.
The question this arises how do you convert from decimal to these other bases? Well this is a more difficult question to answer. There is no direct form equation like what is shown above for that. This has to do with the number of unknowns within the equation and we only have 1 equation. If you are trying to convert to hex, we have 8 unknowns (
). To solve this we would need 8 equations, which we don't have.
So to solve this we need to use an algorithm. Instead of writing this out in completion here, check out this post where someone already figured it out and performed the conversions for you.
Most algorithms involve recursive division where you divide the number by the base value. The remainder goes into the position and you divide again the base value into the quotient until the quotient is 0. It is fairly simple, but these guys explain it better.
I hope this helps give a better understanding of Numerical Base Systems, especially hexadecimal. Once you understand it, it is actually rather simple.
For the programmers out there, I have one final treat! If you want to start working in C# entering hex or binary values into your code directly as literals you can write them in the following ways: Byte value = 0xFF; // Hexadecimal Byte value = 0b10011101; // Binary (C# 6.0+) Have a good day of engineering and innovation!
Check out our thoughts here.
There is one, and only one, primary focus that any software developer acknowledge: the ability for software to be maintainable. Of course, correctness, functionality, and performance are all important, these will always be easier to address with maintainable software.