How to avoid scientific notation for large numbers in JavaScript?

后端 未结 22 1919
無奈伤痛
無奈伤痛 2020-11-22 00:31

JavaScript converts a large INT to scientific notation when the number becomes large. How can I prevent this from happening?

相关标签:
22条回答
  • 2020-11-22 01:08

    If you are just doing it for display, you can build an array from the digits before they're rounded.

    var num = Math.pow(2, 100);
    var reconstruct = [];
    while(num > 0) {
        reconstruct.unshift(num % 10);
        num = Math.floor(num / 10);
    }
    console.log(reconstruct.join(''));
    
    0 讨论(0)
  • 2020-11-22 01:09

    There's Number.toFixed, but it uses scientific notation if the number is >= 1e21 and has a maximum precision of 20. Other than that, you can roll your own, but it will be messy.

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

    Above uses cheap-'n'-easy string repetition ((new Array(n+1)).join(str)). You could define String.prototype.repeat using Russian Peasant Multiplication and use that instead.

    This answer should only be applied to the context of the question: displaying a large number without using scientific notation. For anything else, you should use a BigInt library, such as BigNumber, Leemon's BigInt, or BigInteger. Going forward, the new native BigInt (note: not Leemon's) should be available; Chromium and browsers based on it (Chrome, the new Edge [v79+], Brave) and Firefox all have support; Safari's support is underway.

    Here's how you'd use BigInt for it: BigInt(n).toString()

    Example:

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

    Beware, though, that any integer you output as a JavaScript number (not a BigInt) that's more than 15-16 digits (specifically, greater than Number.MAX_SAFE_INTEGER + 1 [9,007,199,254,740,992]) may be be rounded, because JavaScript's number type (IEEE-754 double-precision floating point) can't precisely hold all integers beyond that point. As of Number.MAX_SAFE_INTEGER + 1 it's working in multiples of 2, so it can't hold odd numbers anymore (and similiarly, at 18,014,398,509,481,984 it starts working in multiples of 4, then 8, then 16, ...).

    Consequently, if you can rely on BigInt support, output your number as a string you pass to the BigInt function:

    const n = BigInt("YourNumberHere");
    

    Example:

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

    0 讨论(0)
  • 2020-11-22 01:13

    You can also use YourJS.fullNumber. For instance YourJS.fullNumber(Number.MAX_VALUE) results in the following: 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    It also works for really small numbers. YourJS.fullNumber(Number.MIN_VALUE) returns this: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005

    It is important to note that this function will always return finite numbers as strings but will return non-finite numbers (eg. NaN or Infinity) as undefined.

    You can test it out in the YourJS Console here.

    0 讨论(0)
  • 2020-11-22 01:14

    You can use from-exponential module. It is lightweight and fully tested.

    import fromExponential from 'from-exponential';
    
    fromExponential(1.123e-10); // => '0.0000000001123'
    
    0 讨论(0)
提交回复
热议问题