如何避免JavaScript中大数字的科学记数法?注意:

2022-08-30 00:25:48

JavaScript 在字符串上下文中使用时,将超过 21 位数字的整数转换为科学记数法。我正在打印一个整数作为URL的一部分。如何防止转换发生?


答案 1

Number.toFixed,但如果数字>= 1e21并且最大精度为20,则它使用科学记数法。除此之外,你可以自己滚动,但它会很混乱。

function toFixed(x) {
  if (Math.abs(x) < 1.0) {
    var e = parseInt(x.toString().split('e-')[1]);
    if (e) {
        x *= Math.pow(10,e-1);
        x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
    }
  } else {
    var e = parseInt(x.toString().split('+')[1]);
    if (e > 20) {
        e -= 20;
        x /= Math.pow(10,e);
        x += (new Array(e+1)).join('0');
    }
  }
  return x;
}

上面使用廉价的'n'-简单的字符串重复()。您可以使用俄罗斯农民乘法进行定义,并改用它。(new Array(n+1)).join(str)String.prototype.repeat

这个答案应该只适用于问题的上下文:显示一个大数字而不使用科学记数法。对于其他任何内容,您应该使用BigInt库,例如BigNumber,Leemon的BigIntBigInteger。展望未来,新的原生BigInt(注意:不是Leemon的)应该可用;Chromium和基于它的浏览器(Chrome,新的Edge [v79 +],Brave)和Firefox都得到了支持;Safari的支持正在进行中。

以下是您将如何使用BigInt:BigInt(n).toString()

例:

const n = 13523563246234613317632;
console.log("toFixed (wrong): " + n.toFixed());
console.log("BigInt (right):  " + BigInt(n).toString());

请注意,您输出为 JavaScript 数字(不是 BigInt)的任何大于 15-16 位(具体而言,大于 [9,007,199,254,740,992])的整数都可能被舍入,因为 JavaScript 的数字类型(IEEE-754 双精度浮点)不能精确地包含超出该点的所有整数。由于它以2的倍数工作,因此它不能再保持奇数(例如,在18,014,398,509,481,984处,它开始以4的倍数工作,然后是8,然后是16,...)。Number.MAX_SAFE_INTEGER + 1Number.MAX_SAFE_INTEGER + 1

因此,如果您可以依赖支持,请将您的数字输出为传递给函数的字符串:BigIntBigInt

const n = BigInt("YourNumberHere");

例:

const n1 = BigInt(18014398509481985); // WRONG, will round to 18014398509481984
                                      // before `BigInt` sees it
console.log(n1.toString() + " <== WRONG");
const n2 = BigInt("18014398509481985"); // RIGHT, BigInt handles it
console.log(n2.toString() + " <== Right");

答案 2

我知道这是一个较旧的问题,但最近显示活跃。MDN toLocaleString

const myNumb = 1000000000000000000000;
console.log( myNumb ); // 1e+21
console.log( myNumb.toLocaleString() ); // "1,000,000,000,000,000,000,000"
console.log( myNumb.toLocaleString('fullwide', {useGrouping:false}) ); // "1000000000000000000000"

您可以使用选项来格式化输出。

注意:

Number.toLocaleString() 在 16 位小数后舍入,因此...

const myNumb = 586084736227728377283728272309128120398;
console.log( myNumb.toLocaleString('fullwide', { useGrouping: false }) );

...返回。。。

586084736227728400000000000000000000000

如果准确性在预期结果中很重要,这可能是不可取的。