JavaScript converts a large INT to scientific notation when the number becomes large. How can I prevent this from happening?
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(''));
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");
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.
You can use from-exponential module. It is lightweight and fully tested.
import fromExponential from 'from-exponential';
fromExponential(1.123e-10); // => '0.0000000001123'