Why Computers Count in Binary and Programmers Count in Hex
Base 10 is a biological accident. Base 2 is a physical one. Here is why hexadecimal sits between them, and why 255 keeps appearing everywhere.
We count in tens because we have ten fingers. That is the entire reason. There is nothing mathematically special about ten, and a species with eight fingers would have found base 8 equally natural and equally arbitrary.
Computers count in twos for a reason that is not arbitrary at all.
Why two
A digital circuit stores information as voltage. In principle you could use ten voltage levels and build a decimal computer, and people tried in the 1950s.
The problem is noise. Every real circuit has interference, temperature drift and manufacturing variation. With ten levels the gaps between them are small, and telling a 6 from a 7 reliably, billions of times a second, across millions of components, at varying temperatures, is extraordinarily hard.
With two levels the gaps are enormous. Anything below a threshold is 0, anything above it is 1, and the circuit can be wrong by a wide margin without producing an error. That tolerance is what makes computers reliable rather than approximately reliable.
Binary is not chosen for elegance. It is chosen because it is the most robust thing to build out of imperfect physics.
How any base works
Every positional number system is the same idea. Each digit carries a place value equal to the base raised to the power of its position, counting from zero on the right.
In base 10, the number 3,742 means:
3 × 10³ + 7 × 10² + 4 × 10¹ + 2 × 10⁰
3000 + 700 + 40 + 2
Nothing there requires ten. Swap the base for 2 and the place values become 1, 2, 4, 8, 16, 32. Swap it for 16 and they become 1, 16, 256, 4096.
Converting from decimal to another base is repeated division, reading remainders backwards:
156 ÷ 2 = 78 remainder 0
78 ÷ 2 = 39 remainder 0
39 ÷ 2 = 19 remainder 1
19 ÷ 2 = 9 remainder 1
9 ÷ 2 = 4 remainder 1
4 ÷ 2 = 2 remainder 0
2 ÷ 2 = 1 remainder 0
1 ÷ 2 = 0 remainder 1
reading upwards: 10011100
Going the other way is multiply and add: 128 + 16 + 8 + 4 = 156.
Why hexadecimal exists
Binary is correct and unreadable. The byte 10011100 is eight characters that a human loses their place in immediately, and a memory address is thirty-two or sixty-four of them.
Hexadecimal solves this because 16 is 2 to the power of 4. That means every hex digit maps to exactly four binary digits, with no carrying between the groups. Conversion becomes a lookup rather than arithmetic.
1001 1100
9 C -> 0x9C
Split the binary into groups of four from the right, convert each independently, join them up. That is the whole procedure, and it works in both directions.
Hexadecimal is not a different number system that programmers happen to prefer. It is binary, written so a person can say it out loud.
Octal does the same with groups of three, which is why Unix file permissions use it. The mode 755 is 111 101 101: the owner may read, write and execute; group and others may read and execute only. Each digit is exactly three permission bits.
Where you meet all of this
Hex colours. #1E90FF is three bytes: red 30, green 144, blue 255. Each channel gets one byte, so each gets values 0 to 255, written as two hex digits. That is why colour codes are six characters and why they stop where they do.
IP addresses and subnets. A /24 network and a mask of 255.255.255.0 are the same statement: the first 24 bits identify the network. Subnetting only makes sense in binary, which is why it is confusing when taught in decimal.
Hashes. A SHA-256 digest is 256 bits. Written as hex, that is 64 characters, because each character carries 4 bits.
Error codes and memory addresses. Conventionally hex, and the 0x prefix is the signal that says so.
Short identifiers. Base 36 uses 0 to 9 then A to Z, the most you can express with digits and the Latin alphabet. Base 62 adds lowercase. URL shorteners use these to pack more value into fewer characters.
The powers of two worth memorising
A handful of these turn a lot of computing trivia into arithmetic you can do in your head.
2^8 = 256 one byte, values 0 to 255
2^10 = 1,024 one kibibyte
2^16 = 65,536 the port number range
2^32 = 4,294,967,296 IPv4 addresses
2^64 = 18,446,744,073,709,551,616
The 2^32 figure is why IPv4 ran out. Roughly four billion addresses for a planet with more connected devices than that was never going to be enough, and the workarounds we use to cope, chiefly network address translation, are why so much of home networking is complicated. IPv6 uses 128 bits, and 2^128 is large enough that exhaustion is not a practical concern.
Why 255 keeps appearing
Eight bits all set to 1 gives 255, the largest value a single byte holds.
That is why colour channels stop at 255. Why the broadcast address of many subnets ends in 255. Why older games capped inventories, scores and levels at 255, or at 127 when one bit was spent on a sign.
When you see a limit of 255, 127, 65,535 or 32,767 in software, you are not looking at a design decision. You are looking at the edge of a binary type, showing through.
The same is true of the 2,147,483,647 that appears in databases and spreadsheets, which is 2^31 minus 1: the largest signed 32-bit integer. Every one of these numbers is a fingerprint of the physics underneath.
Try it yourself
Free, instant, and nothing you enter leaves your browser.