Thinking in Bits: Hex, Binary, Two's Complement and IEEE 754
July 7, 2026 · DevTools
Most of the time you can ignore how numbers are stored. But the moment you touch a hardware register, a permission bitmask, a network protocol, or a float comparison that "should" be equal, you're back in the world of bits. Here's the mental model.
Why multiple bases exist
The same value wears different clothes depending on context:
DEC 255 HEX FF OCT 377 BIN 11111111
- Hex is compact and maps cleanly to bytes — two hex digits = one byte. Datasheets and colors use it.
- Binary makes individual bits visible, which is what you want when masking flags.
- Octal survives mostly in Unix file permissions (
chmod 755).
Switching between them in your head is a chore. The Programmer Calculator shows all four at once and updates every base as you type — plus a clickable bit grid so you can flip a single bit and watch the value change.
Bitwise operations are just per-bit logic
Flags are the classic use case. Say you have permission bits:
READ = 0b100 (4)
WRITE = 0b010 (2)
EXEC = 0b001 (1)
Combine them with OR:
READ | WRITE = 0b110 = 6
Check one with AND:
0b110 & WRITE = 0b010 → non-zero, so WRITE is set
Toggle with XOR, clear with AND NOT. Shifts (<<, >>) move bits left or right — 1 << 4 is a fast 16, and shifting is how you build masks programmatically.
Two's complement: how negatives work
Computers store signed integers in two's complement. In an 8-bit byte, the top bit is the sign. To get -1, you take 1, invert every bit, and add one:
1 = 00000001
~1 = 11111110
+1 = 11111111 = -1 (as a signed byte)
That same bit pattern 11111111 is 255 unsigned or -1 signed — interpretation depends on the type. This is why an unsigned underflow wraps to a huge number, and why picking the right word size (8/16/32/64-bit) matters. The Programmer Calculator shows both the signed and unsigned interpretation side by side.
Why 0.1 + 0.2 ≠ 0.3
Floats are stored as IEEE 754: a sign bit, an exponent, and a mantissa (fraction). The catch is that 0.1 has no exact binary representation — just like 1/3 has no exact decimal one. The nearest 64-bit double to 0.1 is actually:
0.1000000000000000055511151231257827021181583404541015625
Add a few of those and the tiny errors accumulate, so 0.1 + 0.2 lands at 0.30000000000000004. The fix in code is to compare with a tolerance (an epsilon) or use integer cents instead of dollars.
To see this, open the IEEE 754 inspector in the Programmer Calculator, enter 0.1, and watch the sign/exponent/mantissa breakdown — the mantissa is a repeating pattern that can't terminate.
Takeaways
- Use hex for bytes, binary for flags, and let a tool convert.
- AND to test, OR to set, XOR to toggle, shift to build masks.
- Signed values are two's complement — mind your word size.
- Never compare floats with
==; understand IEEE 754 and use an epsilon.
Keep the Programmer Calculator open next time you're elbow-deep in a register map.