Developers & Technical · Guide · Developer Utilities
How to convert between number bases
The math behind base conversion, binary-hex shortcuts, practical uses (Unix permissions, hex colors, memory), bitwise operations, two's complement.
Binary, octal, decimal, hexadecimal — four number bases cover 99% of what programmers run into. Converting between them is straightforward once you see the pattern, and essential for reading memory dumps, understanding flags, decoding Unicode, working with permissions, or debugging low-level systems. This guide covers the math (it’s all just grouping bits differently), the shortcuts between binary and hex that make mental conversion fast, real uses of each base, and when you should reach for a tool instead of doing it by hand.
Advertisement
What a “base” actually is
A number base is the count of unique digits used to represent values. Decimal uses 10 (0-9); binary uses 2 (0-1); hexadecimal uses 16 (0-9, A-F).
Each digit position represents a power of the base. In decimal, the number 345 means 3×100 + 4×10 + 5×1 — powers of 10 (10^2, 10^1, 10^0).
In binary, 101 means 1×4 + 0×2 + 1×1 = 5 — powers of 2.
In hex, 2F means 2×16 + 15 = 47 — powers of 16.
The four bases you’ll meet in practice
Binary (base 2): digits 0, 1. Native to digital logic and bits. Heavy bit manipulation, hardware, file format parsing.
Octal (base 8): digits 0-7. Each digit maps to 3 bits. Historically used in older systems; now mostly seen in Unix file permissions (chmod 755 is octal).
Decimal (base 10): digits 0-9. Human-facing numbers.
Hexadecimal (base 16): digits 0-9, A-F. Each digit maps to 4 bits. Ubiquitous: memory addresses, color codes (#FF5733), HTTP hex, hashes, Unicode code points.
Decimal → binary
Repeatedly divide by 2 and record remainders; read remainders bottom-up.
Example: 13 in binary.
13 / 2 = 6 remainder 1
6 / 2 = 3 remainder 0
3 / 2 = 1 remainder 1
1 / 2 = 0 remainder 1
Read bottom-up: 1101. Verify: 8 + 4 + 0 + 1 = 13. ✓
Binary → decimal
Multiply each bit by its power of 2 and sum.
Example: 10110 in decimal.
1×16 + 0×8 + 1×4 + 1×2 + 0×1 = 22.
Binary ↔ hex — the shortcut
Each hex digit = 4 bits. This makes hex ↔ binary conversion group-by-group, no math required.
Memorize the 16 nibbles (or look them up the first dozen times):
0=0000, 1=0001, 2=0010, 3=0011, 4=0100, 5=0101, 6=0110, 7=0111, 8=1000, 9=1001, A=1010, B=1011, C=1100, D=1101, E=1110, F=1111.
Binary → hex: group binary into 4-bit chunks from the right, translate each chunk.
11010110 → 1101 0110 → D6.
Hex → binary: expand each hex digit to 4 bits.
B3 → 1011 0011.
Binary ↔ octal — same idea, groups of 3
Each octal digit = 3 bits.
110101 → 110 101 → 65 (octal). Verify: 6×8 + 5 = 53 in decimal; binary 110101 = 32+16+4+1 = 53. ✓
Octal → binary: expand each digit to 3 bits.
755 (octal) → 111 101 101 (binary). Useful for reading chmod permissions: rwx-r-x-r-x.
Decimal ↔ hex
Two approaches:
Direct: repeatedly divide by 16 and record remainders (0-15, with 10-15 as A-F). Read bottom-up.
Via binary: easier mentally for small numbers. Convert decimal → binary → group into 4s → hex.
Example: 202 in hex.
202 / 16 = 12 remainder 10 → A.
12 / 16 = 0 remainder 12 → C.
Read bottom-up: CA. Verify: 12×16 + 10 = 202. ✓
Reading code — base prefixes
Most languages use prefixes to disambiguate:
0b or 0B: binary. 0b1101.
0o or leading 0 (older C/ Python): octal. 0o755 or 0755.
0x or 0X: hex. 0xFF.
No prefix: decimal.
Trap: leading-zero octal in C is a footgun. 075 is 61 decimal, not 75. Modern JavaScript threw this out: 0o75 works; 075 is an error in strict mode.
Why hex for colors, memory, and hashes
Colors (#FF5733): 3 bytes of RGB, each byte 0-255, compactly expressed as 2 hex digits. More readable than decimal (255, 87, 51) and trivially maps to underlying bytes.
Memory addresses (0x7FFEDB5A): address space is naturally aligned with 4-byte or 8-byte boundaries. Hex makes alignment and masking visible.
Hashes (MD5, SHA-256): binary data rendered as hex for readability. 32 hex chars = 16 bytes = 128 bits of MD5.
Unicode code points (U+1F600): the Unicode table is effectively indexed in hex.
Octal for Unix permissions
Each permission triplet (read-write-execute) maps to 3 bits, which conveniently fits one octal digit.
r = 4, w = 2, x = 1. Add to combine: rw = 6, rx = 5, rwx = 7.
755 = owner rwx (7), group rx (5), other rx (5). Common for directories.
644 = owner rw (6), group r (4), other r (4). Common for regular files.
600 = owner rw, group and other nothing. For SSH keys.
Bitwise operations — when base matters
AND, OR, XOR, NOT, bit-shift. All operate on the binary representation regardless of how you wrote the number.
Flag checking: if (flags & FLAG_ADMIN). Defined constants are usually single-bit (0x1, 0x2, 0x4...) and hex or binary makes the bit pattern visible.
Bitmasks: color & 0xFFextracts the last byte. The hex mask reads directly as “ keep these 8 bits”.
Shifts: x << 4 multiplies by 16; x >> 4 divides by 16. Useful for packing 4-bit values into bytes.
Two’s complement — negative binary
Computers represent signed integers using two’s complement. To negate an n-bit binary number: invert all bits and add 1.
-5 in 8-bit two’s complement: 5 is 00000101 → invert → 11111010 → add 1 → 11111011. Verify: 11111011 + 00000101 = 00000000 (with overflow). ✓
An 8-bit byte represents values -128 to 127; 16-bit int represents -32,768 to 32,767; 32-bit int represents approximately ±2.1 billion. A hex FF in signed byte = -1, not 255.
Common mistakes
Mixing signed and unsigned. FF is 255 (unsigned byte) or -1 (signed byte). Always know which.
Off-by-one in bit positions. The rightmost bit is bit 0, not bit 1. Flag for bit 3 is 1 << 3 = 8, not 16.
Reading binary right-to-left inconsistently.The least-significant bit (LSB) is the rightmost. Networks and file formats use big-endian OR little-endian byte ordering — always check the spec.
Confusing base prefix. 010 is 10 in decimal but 8 in octal (in C-family languages).
Run the numbers
Convert any number between bases with the number base converter. Pair with the color converter when translating hex colors to RGB/HSL, and the Base64 encoder/decoder for the higher-base text encoding of arbitrary bytes.
Advertisement