Introduction: Why More Number Systems?
Binary is the language computers speak, but it's tedious for humans. A 32-bit memory address is 32 digits long in binary. Decimal conversion is slow and obscures bit patterns. Hexadecimal solves this: the same address is just 8 characters, and you can instantly see the underlying bits.
This guide covers two alternative number systems that every programmer should master:
- Hexadecimal (Base-16): Uses 0-9 and A-F. One hex digit = exactly 4 bits.
- Octal (Base-8): Uses 0-7. One octal digit = exactly 3 bits.
The Core Insight
16 = 2⁴ and 8 = 2³. This means hex and octal digits map perfectly to groups of binary digits. This isn't coincidence—it's why these number systems exist. They're compact ways to represent binary data.
Hexadecimal Fundamentals
Hexadecimal (often called "hex") is a base-16 number system. Where decimal uses 10 digits and binary uses 2, hexadecimal uses 16 distinct symbols.
The 16 Hexadecimal Digits
Since we only have 10 numeric symbols (0-9), hex borrows the first six letters of the alphabet:
| Decimal | Hex | Binary | Decimal | Hex | Binary |
|---|---|---|---|---|---|
| 0 | 0 | 0000 | 8 | 8 | 1000 |
| 1 | 1 | 0001 | 9 | 9 | 1001 |
| 2 | 2 | 0010 | 10 | A | 1010 |
| 3 | 3 | 0011 | 11 | B | 1011 |
| 4 | 4 | 0100 | 12 | C | 1100 |
| 5 | 5 | 0101 | 13 | D | 1101 |
| 6 | 6 | 0110 | 14 | E | 1110 |
| 7 | 7 | 0111 | 15 | F | 1111 |
Case Doesn't Matter
Hexadecimal letters can be uppercase (A-F) or lowercase (a-f). 0xFF and 0xff are the same value. Style guides vary, but uppercase is traditional and lowercase is common in web development.
Counting in Hexadecimal
Counting in hex works just like decimal, but you count to F before carrying:
Counting from 0 to 32 in Hexadecimal
Decimal: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Hex: 0 1 2 3 4 5 6 7 8 9 A B C D E F
Decimal: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
Hex: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
Notice: hex "10" = decimal 16, hex "20" = decimal 32, hex "FF" = decimal 255, hex "100" = decimal 256.
Place Value in Base-16
Like decimal, each position in hex represents a power of the base:
Place Values in Hexadecimal
Position: 3 2 1 0
Power: 16³ 16² 16¹ 16⁰
Value: 4096 256 16 1
Example: 2B5F in hex
2 × 16³ = 2 × 4096 = 8192
B × 16² = 11 × 256 = 2816
5 × 16¹ = 5 × 16 = 80
F × 16⁰ = 15 × 1 = 15
-------
11103
2B5F₁₆ = 11103₁₀
Hexadecimal ↔ Binary Conversion
This is where hex truly shines. Each hex digit corresponds to exactly 4 binary digits (bits), making conversion trivial once you memorize the table.
Hex to Binary
Simply replace each hex digit with its 4-bit binary equivalent:
Example: Convert A7F2 to Binary
A 7 F 2 ← Hex digits
↓ ↓ ↓ ↓
1010 0111 1111 0010 ← 4 bits each
Result: A7F2₁₆ = 1010011111110010₂
Example: Convert DEADBEEF to Binary
D E A D B E E F
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
1101 1110 1010 1101 1011 1110 1110 1111
DEADBEEF₁₆ = 11011110101011011011111011101111₂
(DEADBEEF is a famous "magic number" in programming)
Binary to Hex
Group binary digits into sets of 4 (from the right), then convert each group:
Example: Convert 110101101011 to Hex
Original: 110101101011
Step 1: Group into 4s from the right
1101 0110 1011
Step 2: Convert each group
1101 → D
0110 → 6
1011 → B
Result: 110101101011₂ = D6B₁₆
Example: Convert 10111 to Hex (padding needed)
Original: 10111 (5 bits)
Step 1: Pad to multiple of 4 from the left
0001 0111
Step 2: Convert each group
0001 → 1
0111 → 7
Result: 10111₂ = 17₁₆
Why Hex is Perfect for Binary
The power of hex is that 16 = 2⁴. This means:
- 1 hex digit = 4 bits (a "nibble")
- 2 hex digits = 8 bits (a byte)
- 4 hex digits = 16 bits (a word on many systems)
- 8 hex digits = 32 bits (a dword)
- 16 hex digits = 64 bits (a qword)
The Practical Advantage
A 32-bit memory address in binary: 11000000101010000000000100000001 (32 digits, impossible to read). In hex: C0A80101 (8 digits, easy to read). That's the same address—192.168.1.1 in IP notation.
Hexadecimal ↔ Decimal Conversion
Hex to Decimal
Multiply each digit by its place value and sum:
Example: Convert 3E8 to Decimal
3E8₁₆
3 × 16² = 3 × 256 = 768
E × 16¹ = 14 × 16 = 224
8 × 16⁰ = 8 × 1 = 8
-----
1000
3E8₁₆ = 1000₁₀ ✓
(3E8 = 1000 is used as HTTP "OK" and common test value)
Example: Convert FF to Decimal
FF₁₆
F × 16¹ = 15 × 16 = 240
F × 16⁰ = 15 × 1 = 15
----
255
FF₁₆ = 255₁₀
(Maximum value for one byte)
Decimal to Hex
Repeatedly divide by 16, keeping the remainders:
Example: Convert 500 to Hex
500 ÷ 16 = 31 remainder 4 → 4
31 ÷ 16 = 1 remainder 15 → F
1 ÷ 16 = 0 remainder 1 → 1
Read remainders bottom to top: 1F4₁₆
Verify: 1×256 + 15×16 + 4×1 = 256 + 240 + 4 = 500 ✓
Example: Convert 65535 to Hex
65535 ÷ 16 = 4095 remainder 15 → F
4095 ÷ 16 = 255 remainder 15 → F
255 ÷ 16 = 15 remainder 15 → F
15 ÷ 16 = 0 remainder 15 → F
65535₁₀ = FFFF₁₆
(Maximum value for 16 bits / 2 bytes)
Octal Fundamentals
Octal (base-8) was more popular in early computing when computer word sizes were often multiples of 3 (12, 24, 36 bits). It's less common now but still appears in specific contexts.
The 8 Octal Digits
| Decimal | Octal | Binary |
|---|---|---|
| 0 | 0 | 000 |
| 1 | 1 | 001 |
| 2 | 2 | 010 |
| 3 | 3 | 011 |
| 4 | 4 | 100 |
| 5 | 5 | 101 |
| 6 | 6 | 110 |
| 7 | 7 | 111 |
Note: Octal only uses digits 0-7. The digits 8 and 9 do not exist in octal!
Octal ↔ Binary Conversion
Each octal digit = exactly 3 binary bits:
Example: Convert 752 (octal) to Binary
7 5 2 ← Octal digits
↓ ↓ ↓
111 101 010 ← 3 bits each
752₈ = 111101010₂
Example: Convert 11010110 (binary) to Octal
Original: 11010110
Group into 3s from right:
011 010 110
↓ ↓ ↓
3 2 6
11010110₂ = 326₈
Where Octal is Still Used
Unix File Permissions
The most common use of octal today. Permissions are three groups of 3 bits (owner/group/other), each with read/write/execute flags. chmod 755 means rwxr-xr-x (111 101 101 in binary).
C/C++ Octal Literals
Numbers starting with 0 are octal in C: int x = 0755; is 493 in decimal. This is a common source of bugs when people write 0-prefixed numbers expecting decimal!
Escape Sequences
Some escape sequences use octal: \101 is 'A' (65 decimal = 101 octal). Though hex escapes (\x41) are more common now.
Unix Permissions Example
Permission: rwxr-xr-x
rwx = 111 = 7 (read+write+execute for owner)
r-x = 101 = 5 (read+execute for group)
r-x = 101 = 5 (read+execute for others)
Octal: 755
Command: chmod 755 myfile
Another example:
rw-r--r-- = 110 100 100 = 644 (common for files)
rwxr-xr-x = 111 101 101 = 755 (common for executables)
Number System Notation
To avoid confusion between number systems, various notation conventions exist:
| Convention | Binary | Octal | Decimal | Hexadecimal |
|---|---|---|---|---|
| Subscript | 1010₂ | 12₈ | 10₁₀ | A₁₆ |
| Prefix (common) | 0b1010 | 012 | 10 | 0xA |
| Suffix | 1010b | 12o | 10d | Ah |
| Hash prefix | — | — | — | #0A (CSS) |
| Ampersand | — | &O12 | — | &HA |
Language-Specific Notations
| Language | Binary | Octal | Hexadecimal |
|---|---|---|---|
| C/C++/Java | 0b1010 (C++14+) | 012 | 0xA or 0XA |
| Python | 0b1010 | 0o12 | 0xA |
| JavaScript | 0b1010 | 0o12 | 0xA |
| Assembly (Intel) | 1010b | 12o or 12q | 0Ah or 0xA |
| CSS | — | — | #RRGGBB |
The Dangerous Octal Prefix
In C/C++, a leading zero makes a number octal. int x = 010; assigns 8, not 10! This trips up programmers who use leading zeros for alignment. Python 3 changed to 0o prefix for octal to avoid this confusion.
Arithmetic in Hexadecimal
While you'll rarely need to do hex arithmetic by hand, understanding it deepens your number system fluency.
Hexadecimal Addition
Add digits, carrying when the sum exceeds F (15):
Example: 3A + 2F
3 A
+ 2 F
-----
Position 0: A + F = 10 + 15 = 25
25 = 16 + 9 = 10₁₆ (write 9, carry 1)
Position 1: 3 + 2 + 1(carry) = 6
Result: 3A + 2F = 69₁₆
Verify: 3A = 58, 2F = 47, 58 + 47 = 105 = 69₁₆ ✓
Example: FF + 1
F F
+ 1
-----
Position 0: F + 1 = 15 + 1 = 16 = 10₁₆ (write 0, carry 1)
Position 1: F + 0 + 1(carry) = 16 = 10₁₆ (write 0, carry 1)
Position 2: 0 + 0 + 1(carry) = 1
Result: FF + 1 = 100₁₆ = 256₁₀
(This is exactly like 99 + 1 = 100 in decimal)
Hexadecimal Subtraction
Example: 5C - 2E
5 C
- 2 E
-----
Position 0: C - E = 12 - 14 (need to borrow!)
Borrow 1 from position 1: 12 + 16 = 28
28 - 14 = 14 = E
Position 1: 5 - 1(borrowed) - 2 = 2
Result: 5C - 2E = 2E₁₆
Verify: 5C = 92, 2E = 46, 92 - 46 = 46 = 2E₁₆ ✓
Practical Tip
In practice, programmers convert to decimal or binary, do the math, then convert back. Or they just use a calculator! Hand calculation is mainly useful for building intuition.
Memory Addresses and Hexadecimal
Memory addresses are almost always displayed in hexadecimal. This is the primary reason every programmer must be fluent in hex.
Why Hex for Addresses?
- Compactness: 8 hex digits vs. 32 binary or up to 10 decimal digits
- Bit visibility: You can see the binary pattern directly
- Alignment: Powers of 2 have recognizable patterns in hex
- Convention: It's what debuggers, disassemblers, and documentation use
Common Address Patterns
| Address | Significance |
|---|---|
| 0x00000000 | Null pointer / start of address space |
| 0x00400000 | Typical Windows executable base address |
| 0x7FFFFFFF | End of 32-bit user space (2GB) |
| 0x80000000 | Start of kernel space (32-bit Windows) |
| 0xDEADBEEF | Magic number to mark uninitialized memory |
| 0xCAFEBABE | Java class file magic number |
| 0xFFFFFFFF | Maximum 32-bit address / -1 in signed |
Reading a Memory Dump
Typical Memory Dump Format
Address Hex Content ASCII
------- ------------------------------- ----------------
0x1000 48 65 6C 6C 6F 20 57 6F 72 6C 64 Hello World
0x100B 21 0A 00 00 00 00 00 00 00 00 00 !...........
0x1016 01 02 03 04 05 06 07 08 09 0A 0B ............
Each pair of hex digits = one byte
0x48 = 'H', 0x65 = 'e', 0x6C = 'l', etc.
Pointer Arithmetic
When debugging, you'll often need to calculate memory offsets:
Example: Finding Array Element
Array starts at: 0x7FFF0100
Element size: 4 bytes (int)
Want element index: 5
Address = 0x7FFF0100 + (5 × 4)
= 0x7FFF0100 + 20
= 0x7FFF0100 + 0x14
= 0x7FFF0114
Element 5 is at address 0x7FFF0114
Color Codes: RGB in Hexadecimal
One of the most common uses of hexadecimal is representing colors in web development and graphics.
RGB Color Model
Colors are specified as Red, Green, Blue intensities, each from 0-255 (one byte):
Hex Color Format: #RRGGBB
#FF0000 = Red: FF (255), Green: 00 (0), Blue: 00 (0) = Pure Red
#00FF00 = Red: 00 (0), Green: FF (255), Blue: 00 (0) = Pure Green
#0000FF = Red: 00 (0), Green: 00 (0), Blue: FF (255) = Pure Blue
#FFFFFF = All maximum = White
#000000 = All zero = Black
#808080 = All half (128) = Gray
Common Color Values
| Color | Hex Code | RGB Values |
|---|---|---|
| Red | #FF0000 | 255, 0, 0 |
| Green (Lime) | #00FF00 | 0, 255, 0 |
| Blue | #0000FF | 0, 0, 255 |
| Yellow | #FFFF00 | 255, 255, 0 |
| Magenta | #FF00FF | 255, 0, 255 |
| Cyan | #00FFFF | 0, 255, 255 |
| Orange | #FFA500 | 255, 165, 0 |
| Purple | #800080 | 128, 0, 128 |
Shorthand Notation
CSS allows 3-digit shorthand when each pair is the same digit:
Shorthand Examples
#FFF = #FFFFFF (white)
#000 = #000000 (black)
#F00 = #FF0000 (red)
#0F0 = #00FF00 (green)
#00F = #0000FF (blue)
#ABC = #AABBCC (light grayish blue)
Rule: Each digit is doubled
#XYZ becomes #XXYYZZ
RGBA: Adding Transparency
A fourth byte can specify alpha (transparency):
RGBA Format: #RRGGBBAA
#FF000080 = Red at 50% opacity
#0000FF40 = Blue at 25% opacity
#000000CC = Black at 80% opacity
Alpha: 00 = fully transparent, FF = fully opaque
80₁₆ = 128₁₀ = 50% opacity
Hexadecimal in Programming
Hex appears constantly in programming. Here are the most common uses:
Bit Manipulation
Common Bitmasks
// Check if bit 3 is set
if (value & 0x08) { ... }
// Set bit 5
value |= 0x20;
// Clear bit 7
value &= ~0x80; // OR: value &= 0x7F;
// Extract low nibble
low = value & 0x0F;
// Extract high nibble
high = (value >> 4) & 0x0F;
Why hex? 0x08 shows "bit 3" clearly:
0x08 = 0000 1000
↑ bit 3
Magic Numbers and Constants
| Hex Value | Meaning | Usage |
|---|---|---|
| 0xDEADBEEF | "Dead beef" | Uninitialized memory marker |
| 0xCAFEBABE | "Cafe babe" | Java class file signature |
| 0xFEEDFACE | "Feed face" | macOS Mach-O signature |
| 0xBAADF00D | "Bad food" | Windows LocalAlloc marker |
| 0x8BADF00D | "Ate bad food" | Apple watchdog timeout |
| 0x7F454C46 | ".ELF" | ELF executable signature |
| 0x504B0304 | "PK.." | ZIP file signature |
Character Codes
ASCII in Hexadecimal
Common ASCII values:
0x00 = NUL (null terminator)
0x0A = LF (line feed, \n)
0x0D = CR (carriage return, \r)
0x20 = Space
0x30-0x39 = '0'-'9' (digits)
0x41-0x5A = 'A'-'Z' (uppercase)
0x61-0x7A = 'a'-'z' (lowercase)
Lowercase = Uppercase + 0x20
'A' (0x41) + 0x20 = 'a' (0x61)
Network and Protocol Data
Ethernet Frame in Hex
MAC Address: 00:1A:2B:3C:4D:5E
Each pair is one byte:
00 1A 2B 3C 4D 5E = 6 bytes
IP Address: 192.168.1.1
In hex: C0.A8.01.01
192 = 0xC0
168 = 0xA8
1 = 0x01
1 = 0x01
Working with Hex Editors
Hex editors display file contents as hexadecimal bytes, allowing you to inspect and modify binary data directly.
Popular Hex Editors
- HxD (Windows) - Free, fast, full-featured
- Hex Fiend (macOS) - Free, native Mac app
- xxd (Unix) - Command-line hex dump tool
- hexdump (Unix) - Another command-line option
- VS Code Hex Editor - Extension for VS Code
Reading Hex Editor Output
Typical Hex Editor Display
Offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ASCII
-------- ----------------------------------------------- ----------------
00000000 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 .PNG........IHDR
00000010 00 00 01 00 00 00 01 00 08 02 00 00 00 D3 10 3F ...............?
00000020 31 00 00 00 01 73 52 47 42 00 AE CE 1C E9 00 00 1....sRGB.......
Components:
- Offset: Position in file (hex)
- Hex bytes: 16 bytes per row
- ASCII: Printable characters (. for non-printable)
The 89 50 4E 47 at start identifies this as a PNG image.
File Signatures (Magic Numbers)
| Hex Signature | File Type |
|---|---|
| 89 50 4E 47 | PNG image |
| FF D8 FF | JPEG image |
| 47 49 46 38 | GIF image |
| 50 4B 03 04 | ZIP archive |
| 25 50 44 46 | PDF document |
| 4D 5A | Windows EXE/DLL |
| 7F 45 4C 46 | Linux ELF executable |
| 1F 8B | GZIP compressed |
Why File Signatures Matter
File extensions can be changed, but signatures can't be faked. Security tools check signatures to identify file types regardless of extension. A malicious "image.jpg" might have an EXE signature (4D 5A), revealing it as an executable.
Practice Problems with Solutions
Conversion Problems
Problem 1: Convert 0xBEEF to binary and decimal
Show Solution
Binary:
B E E F
1011 1110 1110 1111
BEEF₁₆ = 1011111011101111₂
Decimal:
B × 16³ = 11 × 4096 = 45056
E × 16² = 14 × 256 = 3584
E × 16¹ = 14 × 16 = 224
F × 16⁰ = 15 × 1 = 15
------
48879
BEEF₁₆ = 48879₁₀ ✓
Problem 2: Convert 11111010 binary to hex and octal
Show Solution
Hex (group by 4):
1111 1010
F A
11111010₂ = FA₁₆ ✓
Octal (group by 3):
011 111 010
3 7 2
11111010₂ = 372₈ ✓
Problem 3: Convert decimal 1000 to hex
Show Solution
1000 ÷ 16 = 62 remainder 8 → 8
62 ÷ 16 = 3 remainder 14 → E
3 ÷ 16 = 0 remainder 3 → 3
1000₁₀ = 3E8₁₆ ✓
Practical Problems
Problem 4: What Unix permission is rwxr-x--- in octal?
Show Solution
rwx = 111 = 7
r-x = 101 = 5
--- = 000 = 0
rwxr-x--- = 750₈ ✓
Problem 5: What color is #FF8C00?
Show Solution
R: FF = 255 (maximum)
G: 8C = 140 (about 55%)
B: 00 = 0 (none)
High red + medium green + no blue = Orange
Specifically, this is "Dark Orange" in CSS.
Problem 6: Add 0x3A + 0x5F without converting to decimal
Show Solution
3 A
+ 5 F
-----
Position 0: A + F = 10 + 15 = 25
25 - 16 = 9, carry 1
Position 1: 3 + 5 + 1 = 9
Result: 99₁₆
Verify: 0x3A = 58, 0x5F = 95
58 + 95 = 153
153 = 9×16 + 9 = 0x99 ✓
Summary
You've now mastered hexadecimal and octal—the essential tools for working with binary data in a human-readable format.
- Hexadecimal (base-16) uses 0-9 and A-F; each digit = 4 bits
- Octal (base-8) uses 0-7; each digit = 3 bits
- Conversion between hex/octal and binary is trivial once you know the digit mappings
- Hex is essential for memory addresses, color codes, and debugging
- Octal survives mainly in Unix file permissions
- File signatures help identify file types regardless of extension
These skills will serve you daily as a programmer, whether you're debugging memory issues, working with network protocols, designing web interfaces, or analyzing binary files.