About number bases
A number base (or radix) is the count of distinct digits used to write a value. Decimal uses 10 digits (0-9), binary uses 2 (0, 1), octal uses 8 (0-7), and hexadecimal uses 16 (0-9, A-F). The value is the same, only the notation changes - just as "ten" and "X" both mean the same count. Computers store every value as binary, but humans find binary tedious to read, so programmers compress it into hex (1 hex digit per 4 binary digits) or, historically, octal (1 octal digit per 3 binary digits).
How conversion works
- Source to decimal: Multiply each digit by the base raised to its position from the right. Binary 10101010 = 1×128 + 0×64 + 1×32 + 0×16 + 1×8 + 0×4 + 1×2 + 0×1 = 170.
- Decimal to target: Repeatedly divide by the target base. Take the remainders bottom up. 170 / 16 = 10 r 10 (=A); 10 / 16 = 0 r 10 (=A). Read bottom up: AA.
- Binary to hex shortcut: Group binary digits in fours from the right; each group is one hex digit. 1010 1010 = A A.
- Binary to octal shortcut: Group in threes from the right; each group is one octal digit. 010 101 010 = 2 5 2.
- Two's complement: For a signed N-bit number, the leftmost bit means -2^(N-1). 10101010 unsigned = 170, but signed 8-bit = 170 - 256 = -86.
Common values reference
Memorise this table and you can mentally convert most byte-level values:
| Value | Binary | Decimal | Hex | Octal |
|---|---|---|---|---|
| Zero | 0000 | 0 | 0x0 | 0o0 |
| One | 0001 | 1 | 0x1 | 0o1 |
| Ten | 1010 | 10 | 0xA | 0o12 |
| Sixteen | 0001 0000 | 16 | 0x10 | 0o20 |
| Byte max (unsigned) | 1111 1111 | 255 | 0xFF | 0o377 |
| Sample 0xAA | 1010 1010 | 170 | 0xAA | 0o252 |
| 16-bit max | 1111 1111 1111 1111 | 65535 | 0xFFFF | 0o177777 |
| 32-bit max | ...1111 (32 ones) | 4294967295 | 0xFFFFFFFF | 0o37777777777 |
Common bit-twiddling tricks every programmer should know
These tricks turn slow arithmetic into single-cycle bitwise operations:
- Check if odd:
x & 1returns 1 if x is odd, 0 if even. Faster thanx % 2on older compilers. - Multiply by power of 2:
x << nequals x × 2^n.x << 3is x × 8. - Divide by power of 2:
x >> nequals x / 2^n for unsigned values. - Set bit n:
x | (1 << n)turns on the nth bit. - Clear bit n:
x & ~(1 << n)turns off the nth bit. - Toggle bit n:
x ^ (1 << n)flips the nth bit. - Test bit n:
(x >> n) & 1returns the nth bit as 0 or 1. - XOR swap:
a ^= b; b ^= a; a ^= b;swaps two integers without a temp variable. - Check power of 2:
(x & (x - 1)) == 0is true only if x is a power of 2 (or zero).
Why programmers care about number bases
Bases come up everywhere in low-level work:
- Memory addresses are always shown in hex: 0x7FFE0000.
- Colour codes in CSS and design tools use hex: #FF6B35 means red=255, green=107, blue=53.
- MAC addresses are six bytes in hex: AA:BB:CC:11:22:33.
- Unicode code points are stated in hex: U+1F600 = grinning face emoji.
- File permissions on Unix use octal: chmod 755 = rwxr-xr-x.
- Network masks are subnet boundaries that only line up cleanly on binary boundaries.
- Bitmasks for compact option storage. 0b00001111 means "options 1-4 enabled".
Worked example: convert 0xCAFEBABE
This is a famous "magic number" used in Java class files. Let us convert it to binary, decimal, and octal:
- Hex to binary: Each hex digit becomes 4 binary digits. C=1100, A=1010, F=1111, E=1110, B=1011, A=1010, B=1011, E=1110. Concatenated: 1100 1010 1111 1110 1011 1010 1011 1110.
- Hex to decimal: 0xCAFEBABE = 12×16^7 + 10×16^6 + 15×16^5 + 14×16^4 + 11×16^3 + 10×16^2 + 11×16^1 + 14×16^0 = 3,405,691,582.
- Hex to octal: Group the binary in threes from the right: 11 001 010 111 111 101 011 101 010 111 110 = 31277535276 (in octal, written 0o31277535276).
- Bit length: 32 bits exactly, since 8 hex digits × 4 bits = 32.
- Signed interpretation: The top bit is 1, so signed 32-bit value = 3,405,691,582 - 4,294,967,296 = -889,275,714.
Number bases at a glance
| Base | Digits | Prefix | When to use |
|---|---|---|---|
| Binary (base 2) | 0, 1 | 0b | Bitmasks, hardware registers, low-level debugging. |
| Octal (base 8) | 0-7 | 0o or leading 0 | Unix file permissions (chmod 755), older minicomputers. |
| Decimal (base 10) | 0-9 | (none) | Everyday human-readable values. |
| Hexadecimal (base 16) | 0-9, A-F | 0x or # | Memory addresses, colour codes, hash digests, MAC addresses. |
The formula explained
Conversion between bases is rooted in positional notation:
value = d_(n-1) × b^(n-1) + d_(n-2) × b^(n-2) + ... + d_1 × b^1 + d_0 × b^0
where b = base, d_i = digit at position i (rightmost = 0).
For binary to hex, the shortcut groups 4 binary digits into 1 hex digit because 2^4 = 16. For binary to octal, 3 binary digits group into 1 octal digit because 2^3 = 8. The shortcuts work because the bases are powers of 2.
For decimal-to-other-base, repeatedly divide by the target base and read the remainders bottom up. For example, 170 in hex: 170/16 = 10 remainder 10 (=A), 10/16 = 0 remainder 10 (=A). Reading bottom up: AA.
Frequently asked questions
What is the difference between signed and unsigned binary?
Unsigned binary uses every bit for the value, so 8 bits go from 0 to 255 and 32 bits go from 0 to ~4.3 billion. Signed binary reserves the leftmost bit as the sign bit, encoding negatives in two's complement, so 8 bits go from -128 to 127 and 32 bits go from roughly -2.1 billion to +2.1 billion. The same bit pattern can mean two different decimal values depending on which interpretation the program uses.
What is two's complement?
Two's complement is the standard way every modern CPU stores signed integers. To negate a value, invert all the bits and add one. The advantage is that the hardware can add and subtract using a single adder circuit without a separate sign bit, and there is exactly one representation for zero (no negative zero). The leftmost bit in two's complement effectively carries a negative weight: in an 8-bit number it represents -128 rather than +128.
Why is hexadecimal used so much in programming?
Hex is compact and aligns naturally with bytes. Every hex digit equals exactly 4 binary digits, so a 32-bit number fits in 8 hex digits instead of 32 binary ones. Two hex digits make exactly one byte, which is why memory addresses, MAC addresses, colour codes (#FF0000), and bitmasks all use hex. It also is much easier to spot patterns (0xDEADBEEF, 0xCAFEBABE) and detect corruption at a glance.
What is the difference between a bit and a byte?
A bit is a single binary digit, holding 0 or 1. A byte is 8 bits, holding values 0 to 255 unsigned or -128 to 127 signed. Memory and file sizes are measured in bytes; network bandwidth is often measured in bits per second. The convention "100 Mbps" means 100 million bits per second, which is only 12.5 megabytes per second.
Why does 16-bit colour give 65,536 values?
16 bits means 2^16 distinct combinations of 0s and 1s, which equals 65,536 exactly. Each combination maps to a unique colour index. 24-bit (true-colour) has 2^24 = 16,777,216 values, which is why "16.7 million colours" is a marketing staple. 32-bit colour adds an 8-bit alpha channel on top.
How big a number can fit in 32 bits?
Unsigned 32-bit holds 0 to 4,294,967,295 (about 4.3 billion). Signed 32-bit holds -2,147,483,648 to 2,147,483,647 (about plus or minus 2.1 billion). This is why old systems with 32-bit IDs hit a hard ceiling at 2 billion users (Twitter's snowflake ID expansion, YouTube's video counter rollover) or 4 GB file sizes on legacy FAT32 disks.
What is IEEE 754 floating point?
IEEE 754 is the binary representation standard for floating-point numbers used by virtually every CPU and language. A 32-bit float has 1 sign bit, 8 exponent bits, and 23 mantissa bits, giving roughly 7 significant decimal digits and a range up to 3.4 x 10^38. A 64-bit double has 1 sign bit, 11 exponent bits, and 52 mantissa bits, giving 15-17 significant decimal digits. This is also why 0.1 + 0.2 does not equal 0.3 exactly in JavaScript.
Why are some bit-twiddling tricks faster than arithmetic?
CPU instructions for bitwise AND, OR, XOR, and shift run in a single clock cycle, whereas multiply and divide may take 3-30 cycles. Common tricks: x & 1 tests if x is odd, x << n multiplies by 2^n, x >> n divides by 2^n (for unsigned), and x ^ y swaps two values without a temp variable. These are pervasive in performance-critical code, embedded systems, and graphics shaders.
