Programmers routinely switch between four number systems: binary (base 2), octal (base 8), decimal (base 10), and hexadecimal (base 16). Knowing how to convert between them by hand — and in code — saves you every time you debug memory addresses, file permissions, or colour values.
Why four number systems?
| Base | Digits used | Common uses |
|---|---|---|
| 2 (binary) | 0–1 | CPU instructions, bit flags, network masks |
| 8 (octal) | 0–7 | Unix file permissions (chmod 755) |
| 10 (decimal) | 0–9 | Human-readable numbers |
| 16 (hex) | 0–9, A–F | Colours (#FF5733), memory addresses, byte values |
Positional notation — the universal key
Every base works the same way. A number d₃d₂d₁d₀ in base B equals:
d₃ × B³ + d₂ × B² + d₁ × B¹ + d₀ × B⁰
Example — binary 1011 in decimal:
1×2³ + 0×2² + 1×2¹ + 1×2⁰
= 8 + 0 + 2 + 1
= 11
Example — hex 2F in decimal:
2×16¹ + 15×16⁰
= 32 + 15
= 47
Decimal → any base (repeated division)
To convert decimal to base B: divide by B, collect remainders bottom-to-top.
Decimal 47 → hexadecimal
47 ÷ 16 = 2 remainder 15 (F)
2 ÷ 16 = 0 remainder 2
Read remainders bottom-to-top: 2F
Decimal 26 → binary
26 ÷ 2 = 13 remainder 0
13 ÷ 2 = 6 remainder 1
6 ÷ 2 = 3 remainder 0
3 ÷ 2 = 1 remainder 1
1 ÷ 2 = 0 remainder 1
Read bottom-to-top: 11010
Decimal 255 → octal
255 ÷ 8 = 31 remainder 7
31 ÷ 8 = 3 remainder 7
3 ÷ 8 = 0 remainder 3
Read bottom-to-top: 377
Any base → decimal (positional sum)
Multiply each digit by B raised to its position (rightmost = position 0), then sum.
Already shown above — the formula is identical for all bases.
Binary ↔ octal shortcut (groups of 3)
One octal digit maps exactly to three binary digits:
| Octal | Binary |
|---|---|
| 0 | 000 |
| 1 | 001 |
| 2 | 010 |
| 3 | 011 |
| 4 | 100 |
| 5 | 101 |
| 6 | 110 |
| 7 | 111 |
Convert binary 110 101 011 → split into groups of 3 from the right → 6 5 3 → octal 653.
Reverse: octal 24 → 010 100 → binary 10100.
Binary ↔ hex shortcut (groups of 4)
One hex digit maps exactly to four binary digits (a nibble):
| Hex | Binary |
|---|---|
| 0 | 0000 |
| 1 | 0001 |
| ... | ... |
| 9 | 1001 |
| A | 1010 |
| B | 1011 |
| C | 1100 |
| D | 1101 |
| E | 1110 |
| F | 1111 |
Convert binary 1111 0011 → F 3 → hex F3.
Reverse: hex A9 → 1010 1001 → binary 10101001.
Quick-reference conversion table
| Decimal | Binary | Octal | Hex |
|---|---|---|---|
| 0 | 0000 | 0 | 0 |
| 8 | 1000 | 10 | 8 |
| 10 | 1010 | 12 | A |
| 15 | 1111 | 17 | F |
| 16 | 10000 | 20 | 10 |
| 32 | 100000 | 40 | 20 |
| 64 | 1000000 | 100 | 40 |
| 127 | 1111111 | 177 | 7F |
| 128 | 10000000 | 200 | 80 |
| 255 | 11111111 | 377 | FF |
| 256 | 100000000 | 400 | 100 |
Code examples
JavaScript
// Decimal to other bases
const dec = 255;
console.log(dec.toString(2)); // "11111111"
console.log(dec.toString(8)); // "377"
console.log(dec.toString(16)); // "ff"
// Other bases to decimal
console.log(parseInt("11111111", 2)); // 255
console.log(parseInt("377", 8)); // 255
console.log(parseInt("ff", 16)); // 255
// Generic converter
function convertBase(value, fromBase, toBase) {
return parseInt(value, fromBase).toString(toBase).toUpperCase();
}
console.log(convertBase("FF", 16, 2)); // "11111111"
console.log(convertBase("377", 8, 16)); // "FF"
Python
n = 255
# Decimal to other bases
print(bin(n)) # '0b11111111'
print(oct(n)) # '0o377'
print(hex(n)) # '0xff'
print(format(n, 'b')) # '11111111' (no prefix)
print(format(n, 'o')) # '377'
print(format(n, 'x')) # 'ff'
# Other bases to decimal
print(int('11111111', 2)) # 255
print(int('377', 8)) # 255
print(int('ff', 16)) # 255
# Generic converter
def convert_base(value: str, from_base: int, to_base: int) -> str:
decimal = int(value, from_base)
if to_base == 10:
return str(decimal)
if to_base == 2:
return format(decimal, 'b')
if to_base == 8:
return format(decimal, 'o')
if to_base == 16:
return format(decimal, 'X')
# arbitrary base
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
result = []
while decimal:
result.append(digits[decimal % to_base])
decimal //= to_base
return ''.join(reversed(result)) or '0'
print(convert_base('FF', 16, 2)) # '11111111'
print(convert_base('377', 8, 16)) # 'FF'
Go
package main
import (
"fmt"
"strconv"
)
func main() {
n := int64(255)
// Decimal to other bases
fmt.Println(strconv.FormatInt(n, 2)) // "11111111"
fmt.Println(strconv.FormatInt(n, 8)) // "377"
fmt.Println(strconv.FormatInt(n, 16)) // "ff"
// Other bases to decimal
v2, _ := strconv.ParseInt("11111111", 2, 64)
v8, _ := strconv.ParseInt("377", 8, 64)
v16, _ := strconv.ParseInt("ff", 16, 64)
fmt.Println(v2, v8, v16) // 255 255 255
// Generic converter
decimal, _ := strconv.ParseInt("FF", 16, 64)
fmt.Println(strconv.FormatInt(decimal, 2)) // "11111111"
}
PHP
$n = 255;
// Decimal to other bases
echo decbin($n); // "11111111"
echo decoct($n); // "377"
echo dechex($n); // "ff"
// Other bases to decimal
echo bindec('11111111'); // 255
echo octdec('377'); // 255
echo hexdec('ff'); // 255
// Generic converter (using base_convert)
echo base_convert('ff', 16, 2); // "11111111"
echo base_convert('377', 8, 16); // "ff"
// base_convert works for bases 2–36
echo strtoupper(base_convert('1a', 16, 10)); // "26"
Common pitfalls
1. Forgetting leading zeros in byte representations.
Binary 1010 is 4 bits, but a full byte needs 8: 00001010. Use padStart(8, '0') in JS or format(n, '08b') in Python when working with bytes.
2. Case sensitivity in hex.parseInt('FF', 16) and parseInt('ff', 16) both work in most languages, but always normalise to lowercase or uppercase when comparing strings.
3. base_convert precision loss in PHP.
PHP's base_convert uses floats internally. For numbers above 2⁵², use the bcmath extension (bcadd, bcmul) or convert through gmp_strval(gmp_init($value, $from), $to).
4. Confusing 0x, 0o, 0b prefixes.0xFF (hex literal), 0o77 (octal), 0b1010 (binary) are JavaScript/Python source-code prefixes — strip them before parseInt or int() if working with user input.
5. Signed vs unsigned.
In most languages, parseInt('-ff', 16) gives -255. When working with raw byte values, ensure you are using unsigned representations (e.g., >>> 0 in JS to force Uint32, or struct.pack in Python).
6. Octal literals in older JavaScript.
In non-strict mode, 010 is octal 8, not decimal 10. Always use explicit parseInt('10', 8) or 0o10 literals.
Frequently asked questions
What is the fastest way to convert hex to binary?
Use the 4-bit group shortcut: replace each hex digit with its 4-bit binary equivalent directly from the table above. No arithmetic needed.
Why do file permissions use octal (e.g., chmod 755)?
Each Unix permission group (owner/group/other) has three bits (read/write/execute). Three bits = one octal digit, so rwxr-xr-x maps neatly to 7 5 5.
What does 0x mean in front of a number?
It is a prefix indicating hexadecimal in C-family languages and many others. 0xFF = 255 in decimal. Similarly, 0b means binary and 0o means octal in Python/modern JavaScript.
How do I convert a hex colour like #3A7BD5 to RGB?
Split into pairs: 3A = 58 red, 7B = 123 green, D5 = 213 blue. Then parseInt('3A', 16) = 58, etc. Use the Color Converter for instant conversion.
Can I convert between bases other than 2, 8, 10, 16?
Yes — the same repeated-division algorithm works for any base. Python's int(value, base) supports bases 2–36, as does PHP's base_convert.
What is the largest hex value that fits in one byte?FF (hex) = 255 (decimal) = 11111111 (binary). One byte holds 8 bits, so the range is 0–255 unsigned or −128 to 127 signed.