Binary, Octal, Hexadecimal: Number Bases Every Developer Should Know

Understand why computers use binary, how hexadecimal simplifies it, and how to convert between number bases with practical programming examples.

By Belqassim Djafer · Published · Updated

Why Developers Need to Understand Number Bases

Most developers work exclusively in base-10 (decimal) but frequently encounter binary and hexadecimal values in:

  • Memory addresses and pointers
  • Bitwise operations and bit flags
  • Color codes (#FF5500)
  • File permissions (chmod 755)
  • Network masks (255.255.255.0)
  • Unicode code points (U+1F600)
  • Byte-level data processing

Understanding number bases makes these values readable instead of opaque.

The Number Base Concept

A number base (radix) defines how many unique digits are used. The position of each digit represents a power of the base:

  • Base 10 (decimal): digits 0–9. Position values: 1, 10, 100, 1000…
  • Base 2 (binary): digits 0–1. Position values: 1, 2, 4, 8, 16, 32…
  • Base 8 (octal): digits 0–7. Position values: 1, 8, 64, 512…
  • Base 16 (hexadecimal): digits 0–9 and A–F. Position values: 1, 16, 256, 4096…

Binary (Base 2)

Binary is the native language of computers because transistors have two states: on (1) and off (0).

Decimal  Binary    Explanation
0        0000
1        0001
2        0010      1×2¹ + 0×2⁰
3        0011      1×2¹ + 1×2⁰
8        1000      1×2³
15       1111      8+4+2+1
255      11111111  128+64+32+16+8+4+2+1 (one byte, all ones)

Bitwise Operations

Binary shines in bitwise operations, which are used for flags, masks, and low-level performance optimization:

const READ    = 0b001; // 1
const WRITE   = 0b010; // 2
const EXECUTE = 0b100; // 4

// Set permissions using OR
let permissions = READ | WRITE; // 0b011 = 3

// Check permission using AND
const canRead    = (permissions & READ) !== 0;    // true
const canExecute = (permissions & EXECUTE) !== 0; // false

// Toggle a bit using XOR
permissions = permissions ^ WRITE; // Remove WRITE: 0b001 = 1

// Left shift: fast multiplication by powers of 2
const x = 3 << 2; // 3 × 4 = 12 (3 shifted left 2 positions)

// Right shift: fast division by powers of 2
const y = 16 >> 2; // 16 ÷ 4 = 4

Hexadecimal (Base 16)

Hexadecimal is the shorthand notation for binary. One hex digit represents exactly 4 binary digits (a nibble), so one byte (8 bits) is always exactly two hex digits:

Binary      Hex    Decimal
0000        0      0
0001        1      1
0101        5      5
1010        A      10
1111        F      15
1111 1111   FF     255
0001 0000   10     16

This is why memory addresses, colours, and hash values are typically shown in hex — it's much more compact than binary while still mapping directly to bit patterns.

// HEX color → RGB
const hex = 0xFF5500;
const r = (hex >> 16) & 0xFF; // 255
const g = (hex >> 8) & 0xFF;  // 85
const b = hex & 0xFF;         // 0

// File permission in hex (common in C/Unix)
const S_IRUSR = 0o400; // Owner read (octal)
const S_IWUSR = 0o200; // Owner write

Octal (Base 8)

Octal maps 3 binary digits to one octal digit. It was popular in early computing but today its main use is Unix file permissions:

# chmod values
# 7 = 111 binary = read(4) + write(2) + execute(1)
# 5 = 101 binary = read(4) + execute(1)
# 4 = 100 binary = read only

chmod 755 script.sh
# Owner: 7 (rwx), Group: 5 (r-x), Others: 5 (r-x)

chmod 644 config.json
# Owner: 6 (rw-), Group: 4 (r--), Others: 4 (r--)

Converting Between Bases

Decimal to Binary

Divide repeatedly by 2, collect remainders bottom-up:

Convert 42 to binary:
42 ÷ 2 = 21 R 0
21 ÷ 2 = 10 R 1
10 ÷ 2 = 5  R 0
5  ÷ 2 = 2  R 1
2  ÷ 2 = 1  R 0
1  ÷ 2 = 0  R 1
Reading remainders upward: 101010

In JavaScript

// To binary/hex/octal string
(42).toString(2);   // "101010"
(42).toString(16);  // "2a"
(42).toString(8);   // "52"

// From string to decimal
parseInt("101010", 2);  // 42
parseInt("2a", 16);     // 42
parseInt("52", 8);      // 42

// Numeric literals in different bases
const bin = 0b101010;  // 42
const hex = 0x2a;      // 42
const oct = 0o52;      // 42

Signed Numbers and Two's Complement

Computers represent negative numbers using two's complement. For an 8-bit signed integer:

  • Range: -128 to 127
  • -1 = 11111111 (all ones)
  • -128 = 10000000
// JavaScript bitwise ops work on 32-bit signed integers
(-1).toString(2); // "11111111111111111111111111111111" (32 ones)
(-1 >>> 0);       // 4294967295 (unsigned 32-bit representation)

Practical Applications

Reading Network Addresses

IP:   192.168.1.1
Mask: 255.255.255.0

In binary:
192  = 11000000
168  = 10101000
1    = 00000001
1    = 00000001

Mask:
255  = 11111111
255  = 11111111
255  = 11111111
0    = 00000000

Network: 192.168.1.0 (all host bits zeroed)

UUID Structure

UUIDs use hex notation: 550e8400-e29b-41d4-a716-446655440000

Each character is one hex digit (4 bits). The UUID is 128 bits = 32 hex characters.

Conclusion

Binary and hexadecimal are not exotic — they are the daily reality of working at any layer below the application. Bitwise operations, color codes, permissions, network masks, and hash values all make immediate sense once you understand the underlying base-16 representation. Use our Number Base Converter to convert between any base quickly.

Related Tools