DEV Community

Guillaume Martigny
Guillaume Martigny

Posted on

Arbitrary large integer

Problem

At one point or another, while using JS, you should have encounter the limitation of number encoding. The most infamous example is:

0.1 + 0.2 === 0.3 // => false
Enter fullscreen mode Exit fullscreen mode

Javascript encode numbers using 64bits of memory (64 binary digits). Since we want to deal with floating numbers (non-finite set), modern languages have to rely on weird maths.
I'm not going to explain it here, because I don't understand it fully myself. But you should know that storing infinite precision numbers over finite memory is not possible.

Math.PI // => 3.141592653589793 "only" 16 digits long.
Enter fullscreen mode Exit fullscreen mode

As it can lack precision for small number, it's also true for large numbers. As soon as you go higher than Number.MAX_SAFE_INTEGER or 2^53 - 1, you're subject to error.

Number.MAX_SAFE_INTEGER     // => 9007199254740991
Number.MAX_SAFE_INTEGER + 2 // => 9007199254740992 (1 + 2 = 2 ?)
Enter fullscreen mode Exit fullscreen mode

It can get even worse if your integer goes beyond Number.MAX_VALUE or 2^1024 - 1, because JS will treat it as Infinity.

Number.MAX_VALUE // => 1.7976931348623157e+308
Number.MAX_VALUE * 2 // => Infinity
1.8e308 // => Infinity
Enter fullscreen mode Exit fullscreen mode

Solution

Recently, Javascript has a new number representation: BigInt. It's now supported by FireFox (v68), Chrome (v67) and Edge (v76). This allow you to write number as large as your computer memory can handle.

It's extremely easy to use, just add a n character in the end of your numbers.

99 ** 999 // => Infinity
99n ** 999n // => 436073206168265161501341703386462012231079860756206...
Enter fullscreen mode Exit fullscreen mode

If you can't add the n, like when you consume the result of a function, you can wrap it in a constructor.

BigInt(getNumberViewers()) * BigInt(getAverageWatchDuration())
Enter fullscreen mode Exit fullscreen mode

There's a few thing to remember while using BigInts.

First, BigInts are not compatible with regular numbers. So, you need to transform all operand to one or the other when doing maths.

const bigInt = 99n ** 999n;
bigInt * 10 // => TypeError: Cannot mix BigInt and other types
Enter fullscreen mode Exit fullscreen mode

Secondly, BigInts are not compatible with Math. Only basic maths operation are allowed.

Math.max(10n, 20n) // => TypeError: Cannot convert a BigInt value to a number
10n < 20n // => true
Enter fullscreen mode Exit fullscreen mode

Thirdly, while division are supported, they automatically round to the closest to 0 integer.

19n / 10n // => 1n
-19n / 10n // => -1n
Enter fullscreen mode Exit fullscreen mode

Finally, you'll have to consider that BigInt are a bit more ressource consuming than native numbers. So you should be using them only when manipulating ever growing numbers, like timestamps, users actions ...


I hope you enjoy this little article. Look for more articles from me on the right panel and consider following me on Github or Twitter.

Until next time, peace ✌️

Top comments (0)