If you've ever stared at a memory address like 0x7FFE, a Unix permission like 0755, or a color code like #FF5733 and needed to convert it to something you can reason about — this guide is for you. We'll cover how to convert between binary (base 2), octal (base 8), decimal (base 10), and hexadecimal (base 16), both by hand and in code.
The Four Number Systems
Every number system works the same way — each digit represents a power of the base:
System Base Digits Prefix Used For
─────────────────────────────────────────────────────────────
Binary 2 0-1 0b Bitwise ops, flags, networking
Octal 8 0-7 0o Unix permissions (chmod)
Decimal 10 0-9 (none) Human math, everyday use
Hexadecimal 16 0-9, A-F 0x Colors, memory, MAC addresses
Quick Reference Table
Decimal Binary Octal Hex
───────────────────────────
0 0000 0 0
1 0001 1 1
2 0010 2 2
3 0011 3 3
4 0100 4 4
5 0101 5 5
6 0110 6 6
7 0111 7 7
8 1000 10 8
9 1001 11 9
10 1010 12 A
11 1011 13 B
12 1100 14 C
13 1101 15 D
14 1110 16 E
15 1111 17 F
16 10000 20 10
255 11111111 377 FF
Decimal to Binary (by Hand)
Divide by 2 repeatedly and collect the remainders (read bottom to top):
Convert 42 to binary:
42 ÷ 2 = 21 remainder 0
21 ÷ 2 = 10 remainder 1
10 ÷ 2 = 5 remainder 0
5 ÷ 2 = 2 remainder 1
2 ÷ 2 = 1 remainder 0
1 ÷ 2 = 0 remainder 1
Read bottom → top: 101010
42 in decimal = 101010 in binary
Binary to Decimal (by Hand)
Multiply each digit by its power of 2 and sum:
Convert 101010 to decimal:
1×2⁵ + 0×2⁴ + 1×2³ + 0×2² + 1×2¹ + 0×2⁰
= 32 + 0 + 8 + 0 + 2 + 0
= 42
Decimal to Hex (by Hand)
Same method — divide by 16, collect remainders:
Convert 255 to hex:
255 ÷ 16 = 15 remainder 15 (F)
15 ÷ 16 = 0 remainder 15 (F)
Read bottom → top: FF
255 in decimal = FF in hex
Hex to Decimal (by Hand)
Convert 0x1A3F to decimal:
1×16³ + A×16² + 3×16¹ + F×16⁰
= 1×4096 + 10×256 + 3×16 + 15×1
= 4096 + 2560 + 48 + 15
= 6719
The Hex-Binary Shortcut
Each hex digit maps to exactly 4 binary digits. This makes hex-to-binary conversion trivial — just expand each hex digit individually:
Hex: A 3 F 7
Binary: 1010 0011 1111 0111
0xA3F7 = 1010001111110111
// Reverse: group binary into 4-bit chunks
Binary: 1101 0010 1110
Hex: D 2 E = 0xD2E
This is why hex is the preferred notation for binary data — it's compact but trivially convertible to binary.
The Octal-Binary Shortcut
Same idea, but each octal digit maps to 3 binary digits:
Octal: 7 5 5
Binary: 111 101 101
chmod 755 = rwxr-xr-x (owner: rwx, group: r-x, other: r-x)
This is exactly why Unix permissions use octal — each digit cleanly maps to one rwx triplet.
Conversions in JavaScript
// ── Decimal to other bases ──
(42).toString(2) // "101010" (binary)
(42).toString(8) // "52" (octal)
(42).toString(16) // "2a" (hex)
(42).toString(36) // "16" (base 36)
// ── Other bases to decimal ──
parseInt("101010", 2) // 42 (binary → decimal)
parseInt("52", 8) // 42 (octal → decimal)
parseInt("2a", 16) // 42 (hex → decimal)
// ── Hex to binary (via decimal) ──
parseInt("FF", 16).toString(2) // "11111111"
// ── Binary literals ──
const flags = 0b10110; // 22 in decimal
const perms = 0o755; // 493 in decimal
const addr = 0xFF00; // 65280 in decimal
// ── Padding with leading zeros ──
(5).toString(2).padStart(8, '0') // "00000101"
(10).toString(16).padStart(2, '0') // "0a"
Conversions in Python
# ── Decimal to other bases ──
bin(42) # '0b101010'
oct(42) # '0o52'
hex(42) # '0x2a'
# ── Without prefix ──
format(42, 'b') # '101010'
format(42, 'o') # '52'
format(42, 'x') # '2a'
format(42, 'X') # '2A' (uppercase)
# ── Other bases to decimal ──
int('101010', 2) # 42
int('52', 8) # 42
int('2a', 16) # 42
# ── Binary literals ──
flags = 0b10110 # 22
perms = 0o755 # 493
addr = 0xFF00 # 65280
# ── Formatted output ──
f"{255:08b}" # '11111111' (8-digit binary)
f"{255:02x}" # 'ff' (2-digit hex)
f"{255:#010x}" # '0x000000ff' (with prefix, padded)
Conversions in the Command Line
# Using printf
printf "%d\n" 0xFF # 255 (hex → decimal)
printf "%x\n" 255 # ff (decimal → hex)
printf "%o\n" 255 # 377 (decimal → octal)
# Using bc (arbitrary base)
echo "obase=2; 42" | bc # 101010 (decimal → binary)
echo "ibase=16; FF" | bc # 255 (hex → decimal)
echo "ibase=2; 101010" | bc # 42 (binary → decimal)
# Using Python one-liner
python3 -c "print(int('FF', 16))" # 255
python3 -c "print(bin(42))" # 0b101010
Real-World Use Cases
CSS Colors (Hex)
#FF5733 = RGB(255, 87, 51)
FF → 255 (red channel, fully on)
57 → 87 (green channel, low)
33 → 51 (blue channel, very low)
Result: bright red-orange
Unix File Permissions (Octal)
chmod 644 file.txt
6 = 110 → rw- (owner: read + write)
4 = 100 → r-- (group: read only)
4 = 100 → r-- (other: read only)
IP Addresses & Subnet Masks (Binary)
192.168.1.0/24
192 .168 .1 .0
11000000.10101000.00000001.00000000
Subnet mask /24:
11111111.11111111.11111111.00000000
= 255.255.255.0
Bitwise Flags (Binary)
// Feature flags packed into a single integer
const READ = 0b0001; // 1
const WRITE = 0b0010; // 2
const EXECUTE = 0b0100; // 4
const ADMIN = 0b1000; // 8
const userPerms = READ | WRITE; // 0b0011 = 3
// Check permission
if (userPerms & EXECUTE) { /* can execute */ }
// Add permission
const upgraded = userPerms | ADMIN; // 0b1011 = 11
MAC Addresses & Memory (Hex)
MAC: AA:BB:CC:DD:EE:FF
Memory address: 0x7FFEE3B8C940
IPv6: fe80::1%lo0
Two's Complement — Negative Numbers in Binary
Computers represent negative integers using two's complement. For an 8-bit signed integer:
42 = 00101010
-42 = ?
Step 1: Invert all bits: 11010101
Step 2: Add 1: 11010110
-42 in 8-bit two's complement = 11010110 = 0xD6
// Verify: 11010110
// Leading 1 = negative
// Invert: 00101001 = 41
// Add 1: 42 → it's -42 ✓
This is why 0xFF can be either 255 (unsigned) or -1 (signed 8-bit) — it depends on interpretation.
Try It Now
Need to convert a number? Use the free Binary/Decimal/Hex converter on UtilShed — enter a number in any base and get all four representations instantly.
Related tools: