Tuesday, July 1, 2025

Binary and Hex basics

Every good programmer needs to know—of course—how to count and do basic math in the decimal system with digits 0123456789. But good programmers should also know how to count and do basic math in two other bases: binary and hexadecimal. The two are related, and it's especially easy to go between them, so we’ll cover conversions before we wrap up here.

First, binary. We normally count with 0123456789, so we have 10 symbols, and our numbers revolve around powers of 10: 1 is 1, 10 is ten times more; 100 is ten times more than that; 1000 is ten times more still; etc. On the other hand, 0.1 is one tenth of 1; 0.01 is one tenth of 0.1; 0.001 is one tenth of 0.01; and so on.

Binary reduces the symbol load to only two—01. Anything you can do in decimal, you can do in binary, and vice versa. The only difference is that place values aren’t 1s, 10s, 100s, 1000s, etc.—they’re 1s, 2s, 4s, 8s, 16s, etc. So binary numbers roll over to more places sooner than base 10 does (about 3.32 times faster), but how the numbers behave when counting, adding, multiplying, dividing, and subtracting is exactly the same.

And just like 9,999,999 is one less than 10,000,000 (which is a perfect power of 10), the equivalent is that 1111 1111 is one less than 1 0000 0000, which is a perfect power of 2. (In decimal, that’s equivalent to saying that 255 is one less than 256, by the way.)

Here's how I like to convert numbers from decimal to binary. Let’s convert 485.

  • I happen to know the biggest power of 2 less than or equal to 485 is 256 (which is 2*2*2*2… 8 times, or 2^8)
  • Subtract that number from 485, and we’re left with 229.
    • We have 1 grouping of 256, plus 229
  • Now, look at the biggest power of 2 less than 229. That’s 128. Make a note. Subtracting it off leaves 101.
    • 1 group of 256
    • 1 group of 128
  • Now, the biggest power left is 64, and subtracting it off leaves 37.
    • 1 group of 256
    • 1 group of 128
    • 1 group of 64
  • Now do the same for 37. The biggest power is 32. Subtracting it leaves 5.
    • 1 group of 256
    • 1 group of 128
    • 1 group of 64
    • 1 group of 32
  • 5 is smaller than 16 and 8, so we won’t have any groups of those
    • 1 group of 256
    • 1 group of 128
    • 1 group of 64
    • 1 group of 32
    • 0 groups of 16
    • 0 groups of 8
  • But we will have 1 group of 4, and that leaves us with 1 left
    • 1 group of 256
    • 1 group of 128
    • 1 group of 64
    • 1 group of 32
    • 0 groups of 16
    • 0 groups of 8
    • 1 group of 4
    • 0 groups of 2
    • 1 group of 1

We then write the number by converting the vertical list into a horizontal one: 357 in binary is 1 1110 0101. Checking our math is very easy: we can simply add all the powers where we have 1s, and ignore the powers where we have 0s, and the sum should be the number we started with. 256+64+32+4+1 is, in fact, 357, so we did everything right. Notice something: because we only have 2 digits, we can immediately know if our answer is wrong if the parity does not match as expected. If a supposedly even number comes back with a last digit of 1, we did something wrong. If a supposedly odd number comes back with a last digit of 0, we did something wrong.

Adding and subtracting work much the same way as in decimal, only there are more frequent carries or borrowings, since there are fewer symbols.

Hexadecimal uses 16 symbols, as opposed to just 10. In addition to 0123456789, we also use ABCDEF.

So counting in hexadecimal looks like 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, 12…, and that is equivalent in decimal to 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18…

Hexadecimal-binary conversions are nice because 16 is a power of 2, so the mapping between the bases is really easy: much, much easier than either binary or hexadecimal to decimal, or vice versa.

You’ll notice that, earlier in the article, I split up a binary number like 1 0110 0101. This makes seeing things in 4-bit groupings (as opposed to 3 decimal-digits groupings of thousands together, millions, billions, etc.) so much easier, and lets the hexadecimal practically jump off the page.

The conversion becomes almost trivial:

  • Starting from the rightmost place, break up the number into 4-bit segments, as done above: 1 1110 0101.
  • If the left-most segment (the most significant) is less than 4 bits, pad it on the left with zeroes: 0001 1110 010
  • Now, just treat every 4-bit section as a single hex digit—because it is—and convert it, remembering that A is decimal 10, B is decimal 11, C is decimal 12, D is decimal 13, E is decimal 14, and F is decimal 15

·       The number becomes:

  • Left-most group: 0001 in binary is 1 in hex
  • Second group: 1110 in binary is E in hex (because 1110 is 14 in decimal, which is E in hex)
  • Third group: 0101 in binary is 5 in hex

·       So the final number is 1E5 in hexadecimal

To convert this back into decimal, we know that our columns now are 1s, 16s, 256s, etc., so we have

  • 5 1s
  • E 16s (that is, 14 16s), or 224 in this column
  • 1 256

And the sum of all that (5 + 224 + 256) is in fact our original number of 485.

 

No comments:

Post a Comment

Switch

 Other than if/if-else/if-else if-else and the ternary operator, there is yet another common and important conditional expression in Java th...