Skip to content

Number Base Converter — PHP source

Convert numbers between binary, octal, decimal and hexadecimal. BigInt-powered, so it handles arbitrarily large values without precision loss.

This is the PHP implementation — the same logic the interactive tool runs, in a shareable, citable form.

<?php
// number-base — Arbitrary-precision base conversion (GMP).
// Language: PHP.
//
// CosmoDev polyglot showcase port of the `number-base` tool, ported from
// src/lib/numberBase.ts. Display source — part of CosmoDev's polyglot tool pages.
//
// PHP's bundled GMP extension supplies the arbitrary precision that TypeScript
// gets from BigInt, so conversions are exact for inputs of any length. Bases
// 2–36 are supported. GMP ships with PHP's standard distribution (no Composer
// dependency). No crypto is involved — this is pure string and integer logic.

const DIGITS = '0123456789abcdefghijklmnopqrstuvwxyz';

/**
 * Map a single lowercase character to its numeric value: 0–9 for '0'–'9',
 * 10–35 for 'a'–'z'. Returns -1 when the character is not a valid digit.
 */
function digit_value(string $ch): int
{
    $c = ord($ch);
    if ($c >= 48 && $c <= 57) return $c - 48;   // '0'..'9'
    if ($c >= 97 && $c <= 122) return $c - 87;  // 'a'..'z' -> 10..35
    return -1;
}

/**
 * Parse $str as an integer written in $base (2–36) and return a GMP value, or
 * null when the base is out of range or $str contains an invalid digit.
 *
 * A leading sign is honored, and a matching radix prefix (0x/0b/0o) is stripped
 * only when it agrees with $base — so "0xFF" is meaningful for base 16 but
 * rejected for base 10.
 */
function parse_bigint(string $str, int $base): ?GMP
{
    if ($base < 2 || $base > 36) return null;

    $s = strtolower(trim($str));
    $neg = false;
    if (str_starts_with($s, '-'))     { $neg = true; $s = substr($s, 1); }
    elseif (str_starts_with($s, '+')) { $s = substr($s, 1); }

    if (($base === 16 && str_starts_with($s, '0x')) ||
        ($base === 2  && str_starts_with($s, '0b')) ||
        ($base === 8  && str_starts_with($s, '0o'))) {
        $s = substr($s, 2);
    }
    if ($s === '') return null;

    // Horner's method over the digits, all in GMP arithmetic.
    $result = gmp_init(0);
    for ($i = 0, $len = strlen($s); $i < $len; $i++) {
        $d = digit_value($s[$i]);
        if ($d < 0 || $d >= $base) return null;
        $result = gmp_add(gmp_mul($result, $base), $d);
    }
    return $neg ? gmp_neg($result) : $result;
}

/**
 * Render a GMP value as a lowercase string in $base (2–36). Returns the empty
 * string for an out-of-range base; the sign of zero is never emitted.
 */
function format_bigint(GMP $value, int $base): string
{
    if ($base < 2 || $base > 36) return '';
    if (gmp_cmp($value, 0) === 0) return '0';

    $neg = gmp_sign($value) < 0;
    // Work on the magnitude so gmp_mod always yields a non-negative remainder.
    $v = gmp_abs($value);
    $out = '';
    while (gmp_cmp($v, 0) > 0) {
        // The remainder is guaranteed smaller than the base, so it fits in an
        // int and indexes DIGITS directly.
        $rem = gmp_intval(gmp_mod($v, $base));
        $out = DIGITS[$rem] . $out;
        $v = gmp_div_q($v, $base);
    }
    return $neg ? '-' . $out : $out;
}

/**
 * Parse $value in $from_base, then format it in $to_base. Returns null when the
 * input cannot be parsed.
 */
function convert_base(string $value, int $from_base, int $to_base): ?string
{
    $n = parse_bigint($value, $from_base);
    if ($n === null) return null;
    return format_bigint($n, $to_base);
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →