Why JavaScript base-36 conversion appears to be ambiguous
The result of parseInt("welcomeback",36)
is larger than Number.MAX_SAFE_INTEGER
(253-1) and thus cannot be accurately represented. A possible workaround is to perform base conversion with BigInt
manually.
const str = "welcomeback";
const base = 36;
const res = [...str].reduce((acc,curr)=>
BigInt(parseInt(curr, base)) + BigInt(base) * acc, 0n);
console.log(res.toString());
console.log(res.toString(36));
The number data type in JavaScript is a 64-bit floating point number, and it can safely represent integers only up to 2^53-1, see What is JavaScript's highest integer value that a number can go to without losing precision?
The result of parseInt("welcomeback",36)
is above that limit. The result is going to be the closest number that can be represented.
A JS Number can safely hold 10 base-36 digits, so an efficient way to parse it into a BigInt is to split the string into chunks of 10 digits, and combine them. The other answers shows a similar technique using reduce
, here's one using forEach
:
function toBigInt36(str) {
const multiplier = BigInt(Math.pow(36, 10));
const chunks = str.match(/.{1,10}/g);
let result = BigInt(0);
chunks.forEach((chunk) => {
result = result * multiplier + BigInt(parseInt(chunk, 36))
});
return result;
}