6

I am currently writing a piece of JavaScript that uses base 36 encoding.

I came across this problem:

parseInt("welcomeback",36).toString(36)

Appears to return "welcomebacg".

I tested this in the Chrome developer's console and Node.js with the same result.

Is there any logical explanation for this result?

4

2 回答 2

6

的结果parseInt("welcomeback",36)大于Number.MAX_SAFE_INTEGER(2 53 -1),因此无法准确表示。一种可能的解决方法是BigInt手动执行基本转换。

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));

于 2020-08-01T00:21:19.400 回答
2

JavaScript 中的数字数据类型是 64 位浮点数,它只能安全​​地表示最大为 2^53-1 的整数,请参阅JavaScript 在不损失精度的情况下,数字可以达到的最高整数值是多少?

的结果parseInt("welcomeback",36)高于该限制。结果将是可以表示的最接近的数字。

一个 JS Number 可以安全地保存 10 个 base-36 数字,因此将其解析为 BigInt 的一种有效方法是将字符串拆分为 10 个数字的块,然后将它们组合起来。其他答案显示了类似的技术 using reduce,这是一个 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;
}

于 2020-08-01T00:12:16.853 回答