Decimal, Binary and Hexadecimal Number Systems

Featured-18

The extensive use of numbers and various number systems is a commonly understood requirement of digital electronics, but if you’re going to start doing work at the chip level, you need to get familiar with understanding how these number systems interact. Ideally, I think you can just need to read through this page to understand the concepts, then go through the pages on number system conversion and run through the practice problems before finally using tools to do it for you. Your understanding needs to be at a level where you can find bugs and correct them, not do hexadecimal long division in your head.

I want to point out that there are hundreds of resources on the web you can turn to for more information on this exact topic, and many different ways of presenting it. This is how I learned it way back when I had to flip dip switches to set the upper nibble and lower nibble on SCSI cards built with through hole components that had trimmed leads so sharp you’d give the backplane a blood offering when swapping peripherals out.

Decimal Numbering System

A decimal number is comprised of values that go from 0-9 — “deci” is from the latin “decimus” meaning “tenth” and there are ten different values that are possible at each position. When a position reaches the value of 9 and needs to have an additional value of one added to it, the next position to the left is incremented by one and that the original position resets to 0, counting upwards from there.

When you look at a long decimal number, each position is equivalent to the value in that position multiplied by 10 to the power of that position; you’re actually seeing a shorthand representation of the addition of all the equivalent values. I’ve included the leading zeros here for clarity, so the difference between an eight digit value in each of the number systems can be understood.

Decimal Value 42

Decimal Value of 42

Decimal Value 10,807,231

Decimal Value of 10807231

When looking at code, decimal values are represented as you would normally expect to see them, as the number itself.

Binary Numbering System

A binary number is comprised of values that go from 0 to 1 — “bin” is from the latin as well, meaning “two” and there are two different values that are possible at each position. When a position reaches the value of 1 and needs to have an additional value of one added to it, the next position to the left is incremented by one and the original position resets to 0.

This is necessary, because a decimal numbering system is far too complex for a computing system to handle. It needs to be a basic as possible, and nothing is more basic than “YES” or “NO”. When you understand how logic gates can be combined to store binary values, you can start to understand why binary is used.

When you look at a long binary number, each position is equivalent to the value in that position, multiplied by 2 to the power of that position; you’re actually seeing a short hand representation of the addition of all the equivalent values. Again, leading zeros are included for clarity.

Binary Value of 42

Binary Value of 42

Binary Value of 138

Binary Value of 138

When looking at code, some languages don’t provide a way to describe binary values literally as they get very unwieldy past eight digits — the maximum value you can present in binary with eight ones is only 11111111 = 255. Arduino code does allow them however, represented as a whole byte with leading zeros, by using a preceding “B” to indicate that B10010101 is actually 149 and not 10,010,101. Really though, once your comfortable with it, most of the time you just skip the binary and go straight to…

Hexadecimal Numbering System

A hexadecimal number is comprised of values that go from 0 to F — “hex” is from the latin meaning six and “deci” meaning ten, and there are 16 different values that are possible at each position: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. When a position reaches the value of F and needs to have an additional value of one added to it, the next position to the left is incremented by one and the original position resets to 0.

Hexadecimal is used, for most purposes, as a simple way of shortening up binary values that would grow stupendously long if left in their literal representation: four positions of binary numbering can be compressed into a single position of hex. The amount of hex positions you wind up dealing with really boil down to the addressing methods and memory sizes available in the chips you’re dealing with. The Atmel ATmega328P at the heart of an Arduino is an 8-bit microcontroller, so you’d use two hex positions for your operations: eight bits = two sets of four binary positions = one hex position per four binary positions = two hex positions. The very popular ARM Cortex M4 is a 32-bit controller, so you’d use eight hex positions: 32 bits = 8 sets of four binary positions = one hex positions for ever four binary positions = eight hex positions.

When you look at a long hex number, each position is equivalent to the value in that position, multiplied by 16 to the power of that position; you’re actually seeing a short hand representation of the addition of all the equivalent values. Again, leading zeros are included for clarity.

Hexadecimal Value of 42

Hex Value of 42

Hexadecimal Value of 3,019,833,873

Hex Value of 3019833873

When looking at code, most languages will have you prepend a hex value with “0x”, and all letter values in the hex number are capitalized. The two values used as examples above would be shown in code as 0x2A and 0xB3FF0211 respectively.