Number Base Converter — JavaScript source
Convert numbers between binary, octal, decimal and hexadecimal. BigInt-powered, so it handles arbitrarily large values without precision loss.
This is the JavaScript implementation — the same logic the interactive tool runs, in a shareable, citable form.
// number-base - Arbitrary-precision base conversion (BigInt).
// Language: JavaScript (ES2020+, uses native BigInt).
//
// CosmoDev polyglot showcase port of the `number-base` tool, ported from
// src/lib/numberBase.ts. Display source - part of CosmoDev's polyglot tool pages.
//
// The conversion runs entirely on JavaScript's native arbitrary-precision
// BigInt, so results are exact for inputs of any length. Bases 2-36 are
// supported, matching the canonical TypeScript implementation. No crypto or
// external dependencies are involved - this is pure string/number logic.
const DIGITS = '0123456789abcdefghijklmnopqrstuvwxyz';
// Map a single 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 in any base.
function digitValue(ch) {
if (ch >= '0' && ch <= '9') return ch.charCodeAt(0) - 48;
if (ch >= 'a' && ch <= 'z') return ch.charCodeAt(0) - 87;
return -1;
}
// Parse `str` as an integer written in `base` (2-36). Returns a BigInt on
// success, or null when the base is out of range or `str` holds an invalid
// digit. A leading sign (`+`/`-`) is honored, and a radix prefix (`0x`/`0b`/
// `0o`) is tolerated only when it agrees with the requested base - so "0xFF"
// is meaningful for base 16 but rejected for base 10.
export function parseBigInt(str, base) {
if (base < 2 || base > 36) return null;
let s = str.trim().toLowerCase();
let neg = false;
if (s.startsWith('-')) { neg = true; s = s.slice(1); }
else if (s.startsWith('+')) { s = s.slice(1); }
if ((s.startsWith('0x') && base === 16) ||
(s.startsWith('0b') && base === 2) ||
(s.startsWith('0o') && base === 8)) {
s = s.slice(2);
}
if (!s) return null;
// Horner's method over the digits, all in BigInt arithmetic.
let result = 0n;
const b = BigInt(base);
for (const ch of s) {
const d = digitValue(ch);
if (d < 0 || d >= base) return null;
result = result * b + BigInt(d);
}
return neg ? -result : result;
}
// Render a BigInt `value` as a lowercase string in `base` (2-36). Returns the
// empty string for an unsupported base; the sign of zero is never emitted.
export function formatBigInt(value, base) {
if (base < 2 || base > 36) return '';
if (value === 0n) return '0';
let v = value;
let neg = false;
if (v < 0n) { neg = true; v = -v; }
const b = BigInt(base);
let out = '';
// Peel off the least-significant digit each iteration and prepend it.
while (v > 0n) {
out = DIGITS[Number(v % b)] + out;
v /= b;
}
return neg ? '-' + out : out;
}
// Convenience wrapper: parse `value` in `fromBase`, then re-emit it in
// `toBase`. Returns null when the input does not parse.
export function convertBase(value, fromBase, toBase) {
const n = parseBigInt(value, fromBase);
if (n === null) return null;
return formatBigInt(n, toBase);
}
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 →