Modulus(%) operator in Typescript not working correctly for big numbers

Viewed 12636

I'm writing a specific validator and needed the modulus of a 16 digit number. Noticed that the operator % doesn't work correctly after 15 digits. I can rewrite my code to check less digits, but I could not find this limitation anywhere in the documentation. What is the reason for this working badly?

Tried checking these values in a normal .ts file:

console.log(10000000000000000%97); 

console.log(10000000000000001%97);

console.log(10000000000000002%97);

console.log(10000000000000003%97);

console.log(10000000000000004%97);

Expected result when using a the regular calculator is:

62
63
64
65
66

On the other hand, the output was:

62
62
64
66
66
2 Answers

You are running into the quirks of floating point representation. Numbers in JavaScript are represented using the floating point standard. This standard makes tradeoffs between range and precision. The larger the number the less precision you have. This means that really large numbers can't be represented accurately. For example 10000000000000001 can't be represented in this standard, so you actually end up with 10000000000000000. You can test this out if you console.log the numbers:

console.log(10000000000000000);
console.log(10000000000000001);
console.log(10000000000000002);
console.log(10000000000000003);
console.log(10000000000000004);

Output is:

10000000000000000
10000000000000000
10000000000000002
10000000000000004
10000000000000004

If you want to represent large numbers with greater precision you will need to use a custom large number library (ex). There is also proposed bigint support in Javascript, but at least at time of writing this has limited support in browsers.

This is a Javascript problem, not Typescript. The maximum safe integer in Javascript is 2^53 - 1, you can check here:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number

You can use BigInt if you want to work with numbers that big, you can represent them adding an n at the end of the number. If you try this:

console.log(10000000000000000n%97n);

console.log(10000000000000001n%97n);

console.log(10000000000000002n%97n);

console.log(10000000000000003n%97n);

console.log(10000000000000004n%97n);

It should do what you expect.

Edit: as mentioned above BigInt is not supported by some browsers https://caniuse.com/#feat=bigint

Related