Base Conversion in Programming Languages: A Practical Guide

May 28, 20267 min read

Why Base Conversion Matters in Programming

Every programming language stores numbers internally in binary, but developers work with decimal, hexadecimal, octal, and binary representations depending on the task. Color codes use hex. File permissions use octal. Bit masks use binary. Configuration values might arrive as hex strings from an API.

Knowing how to convert between bases in your language of choice — and understanding what happens under the hood — prevents subtle bugs like integer overflow, string formatting errors, and silent truncation.

Built-in Conversion Functions

Most languages provide built-in support for common base conversions. Here's a quick reference:

LanguageDecimal → HexDecimal → BinaryHex → Decimal
Pythonhex(n)bin(n)int(s, 16)
JavaScriptn.toString(16)n.toString(2)parseInt(s, 16)
JavaInteger.toHexString(n)Integer.toBinaryString(n)Integer.parseInt(s, 16)
Gofmt.Sprintf("%x", n)fmt.Sprintf("%b", n)strconv.ParseInt(s, 16, 0)
Rustformat!("{:x}", n)format!("{:b}", n)u32::from_str_radix(s, 16)

Python

Python makes base conversion straightforward with int() and toString() variants:

# Parse any base to decimal
int('FF', 16)    # 255
int('377', 8)    # 255
int('11111111', 2)  # 255

# Decimal to other bases (returns string with prefix)
hex(255)   # '0xff'
oct(255)   # '0o377'
bin(255)   # '0b11111111'

# Format without prefix
format(255, 'x')  # 'ff'
format(255, 'b')  # '11111111'

For bases beyond 16, you need a custom function — Python doesn't include one.

JavaScript

JavaScript uses toString(radix) for output and parseInt(string, radix) for input:

// Decimal to other bases
(255).toString(16)  // 'ff'
(255).toString(8)   // '377'
(255).toString(2)   // '11111111'

// Other bases to decimal
parseInt('ff', 16)    // 255
parseInt('377', 8)    // 255
parseInt('11111111', 2)  // 255

Caveat: parseInt('08') returns 0 in older JavaScript engines because it interpreted the leading 0 as octal. Always pass the radix explicitly.

Java

Java provides Integer and Long class methods:

// Decimal to other bases
Integer.toHexString(255)    // "ff"
Integer.toOctalString(255)  // "377"
Integer.toBinaryString(255) // "11111111"

// Other bases to decimal
Integer.parseInt("ff", 16)    // 255
Integer.parseInt("377", 8)    // 255
Integer.parseInt("11111111", 2)  // 255

For arbitrary bases (2–36), use Integer.toString(n, radix) and Integer.parseInt(s, radix).

Writing a Manual Base Converter

Understanding the algorithm helps you handle cases built-in functions don't cover — like bases above 36 or custom digit sets.

Decimal to Any Base

Divide by the target base repeatedly and collect remainders:

def to_base(n, base):
    if n == 0:
        return '0'
    digits = '0123456789abcdefghijklmnopqrstuvwxyz'
    result = ''
    while n > 0:
        result = digits[n % base] + result
        n //= base
    return result

to_base(255, 16)  # 'ff'
to_base(255, 2)   # '11111111'
to_base(255, 36)  # '73'

Any Base to Decimal

Multiply each digit by its place value and sum:

def from_base(s, base):
    digits = '0123456789abcdefghijklmnopqrstuvwxyz'
    result = 0
    for char in s.lower():
        result = result * base + digits.index(char)
    return result

from_base('ff', 16)    # 255
from_base('11111111', 2)  # 255

Common Pitfalls

Case Sensitivity

Hex strings may arrive uppercase (FF) or lowercase (ff). Always normalize case before parsing, or use case-insensitive comparison.

Zero Prefix Ambiguity

A leading 0 can mean octal or just be a zero-padded decimal. In Python 3, 0123 is a syntax error. In older JavaScript, it parsed as octal. Always use explicit radix parameters.

Negative Numbers

toString(radix) in JavaScript produces a signed representation for negative numbers: (-255).toString(16) returns '-ff'. If you're working with two's complement representations, you need manual bit masking.

Floating-Point Precision

Built-in functions work with integers. Converting large floating-point numbers between bases introduces precision loss. Use BigInt (JavaScript) or decimal (Python) for large values.

Arbitrary Bases Beyond 36

Most built-in converters max out at base 36 (0–9, a–z). For higher bases, extend the digit set:

def to_base62(n):
    """Base62: 0-9, a-z, A-Z — common for URL shorteners."""
    digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    if n == 0:
        return '0'
    result = ''
    while n > 0:
        result = digits[n % 62] + result
        n //= 62
    return result

Base62 is popular for URL shortening and unique ID generation because it produces compact, URL-safe strings.

Key Takeaways

  • Most languages have built-in functions for common bases (2, 8, 10, 16) — learn them before writing custom code
  • Always pass the radix explicitly to parseInt() and similar functions to avoid ambiguity
  • Manual conversion algorithms (divide-and-collect, multiply-and-sum) work for any base up to your digit set size
  • Watch out for case sensitivity, zero-prefix ambiguity, negative number handling, and floating-point precision
  • For bases above 36, extend the digit set with uppercase letters or custom characters
  • Understand the algorithm even if you use built-in functions — it helps debug edge cases

Try It Yourself

Convert between any number base instantly with our free Number Base Converter. Enter a value in decimal, binary, octal, or hex and see all conversions at once.