Base 36转换为BigInt?

21

假设我想将一个36进制编码的字符串转换为一个BigInt,我可以这样做:

BigInt(parseInt(x,36))

但是如果我的字符串超出了一个安全的 JavaScript Number 的范围怎么办?例如:

parseInt('zzzzzzzzzzzzz',36)

然后我开始失去精度。

是否有将解析方法直接转换为 BigInt 的方法?


1
在撰写本文时,答案是否定的:在 BigInt proposal(阶段3草案,2019年2月11日)中没有提到任何类似于 parseInt 的等效物。该提案中唯一提到的字符串转换是 BigInt() 函数本身,但它仅包括2、8、10和16进制。 - Thomas
2
@Thomas https://github.com/tc39/proposal-number-fromstring - Yukulélé
2个回答

14

您可以将数字转换为 bigint 类型。

function convert(value, radix) {
    return [...value.toString()]
        .reduce((r, v) => r * BigInt(radix) + BigInt(parseInt(v, radix)), 0n);
}

console.log(convert('zzzzzzzzzzzzz', 36).toString());

使用更大的块,例如用十个(十一个会返回错误结果)。

function convert(value, radix) { // value: string
    var size = 10,
        factor = BigInt(radix ** size),
        i = value.length % size || size,
        parts = [value.slice(0, i)];

    while (i < value.length) parts.push(value.slice(i, i += size));

    return parts.reduce((r, v) => r * factor + BigInt(parseInt(v, radix)), 0n);
}

console.log(convert('zzzzzzzzzzzzz', 36).toString());


非常好。我不知道parseInt函数也可以使用大于16的基数。那么大于36的基数呢?这个有文档记录吗?(在MDN上没有找到...) - Bart Hofland
没关系,我的问题已经解决了。MDN声明它接受从2到36的基数。 ;) - Bart Hofland
对于更大的基数,您需要一个自定义字符集和自己的函数。 - Nina Scholz
1
我在想我们能不能将它分批处理,每批11个字符?(Number.MAX_SAFE_INTEGER.toString(36).length).. 嗯,我猜是10吧。 - mpen

5
不确定是否有内置的方法,但是将base-X转换为BigInt相当容易实现。
function parseBigInt(
  numberString,
  keyspace = "0123456789abcdefghijklmnopqrstuvwxyz",
) {
  let result = 0n;
  const keyspaceLength = BigInt(keyspace.length);
  for (let i = 0; i < numberString.length; i++) {
    const value = keyspace.indexOf(numberString[i]);
    if (value === -1) throw new Error("invalid string");
    result = result * keyspaceLength + BigInt(value);
  }
  return result;
}

console.log(parseInt("zzzzzzz", 36));
console.log(parseBigInt("zzzzzzz"));
console.log(parseBigInt("zzzzzzzzzzzzzzzzzzzzzzzzzz"));

输出

78364164095
78364164095n
29098125988731506183153025616435306561535n

默认的keyspace相当于使用基数36的parseInt,但如果你需要其他的东西,选项在那里。 :)

这个函数对于任何以 0 结尾的字符串都不能产生正确的结果? - Zak Henry
这个解析数字的函数有错误。parseBigInt('xyz').toString(36) 返回的结果是 zyx。问题在于它以相反的顺序迭代字符串,从而以相反的顺序解析数字。 - lusc
@lusc 我非常确定这个实现做到了它应该做的事情 - 它之所以反向迭代,是因为result = result * number-of-digits + current-digit的操作... - AKX
你试过用parseBigInt('xyz').toString(36)吗?除非我漏掉了什么,它不应该返回zyx - lusc
@lusc 哎呀,是啊。不知道我当时在想什么,也不知道这个问题怎么能够被忽视了整整四年。谢谢! - AKX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接