【问题标题】:Why JavaScript base-36 conversion appears to be ambiguous为什么 JavaScript base-36 转换似乎模棱两可
【发布时间】:2020-11-21 19:28:47
【问题描述】:

我目前正在编写一段使用 base 36 编码的 JavaScript。

我遇到了这个问题:

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

似乎返回"welcomebacg"

我在 Chrome 开发者控制台和 Node.js 中对此进行了测试,结果相同。

这个结果有什么合乎逻辑的解释吗?

【问题讨论】:

  • 我的第一个想法是因为解析的值超过了number可以准确表示的最大可能值(2^53,但是你的值是36^11的顺序)尝试使用较新的 BigInt 类型而不是 number
  • @Dai Yup。 Parseint 给出118479146750471970,大于Number.MAX_SAFE_INTEGER

标签: javascript node.js google-chrome-devtools base base36


【解决方案1】:

parseInt("welcomeback",36) 的结果大于Number.MAX_SAFE_INTEGER (253-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));

【讨论】:

    【解决方案2】:

    JavaScript 中的数字数据类型是 64 位浮点数,它只能安全​​地表示最大为 2^53-1 的整数,请参阅What is JavaScript's highest integer value that a number can go to without losing precision?

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

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

    【讨论】:

    • 我该如何解决这个问题?
    • @nph 也许把字符串分开?在 JS 中连接很容易。
    • @nph 经验法则:每当您发现数字太大时,请分别处理数字。
    • @Calculuswhiz 你怎么能用它来转换整个字符串?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 2022-01-02
    相关资源
    最近更新 更多