geisterfurz007
geisterfurz007

Reputation: 5874

How does addition in JS work with big numbers

While practicing code golf on a discord server we found that our code would stop working once the number got to big and results would start getting messy.

The main calculation is a=a*10+!(a%2) and the first a in the series we produced that would result in unexpected results was a=1010101010101010 (Expected: 10101010101010101 vs Actual: 10101010101010100).

When investigating I found that the calculation 10101010101010100 + 1 = 10101010101010100.
After seeing that, I tried 10101010101010100 + 2 = 10101010101010102 which confused me. Why would adding 1 result in the same value and adding 2 would not?

More examples:

10101010101010100 + 3 = 10101010101010104
10101010101010102 + 1 = 10101010101010104
10101010101010104 + 1 = 10101010101010104

I also tried putting the numbers in Number() to prevent any autoconversion (it's JS after all) but the results were the same.

After a short delay What is JavaScript's highest integer value that a number can go to without losing precision? was posted in said discord and this seems to explain why the results were like they were but I am curious as to what happens underneath the surface of the console that produces these rather unexpected results. Or is the behaviour of arithmetic operations on numbers that big simply defined as undefined in JS?

Upvotes: 2

Views: 143

Answers (1)

Xeraqu
Xeraqu

Reputation: 195

See this documentation.

It mentions that the value of a JavaScript Number is represented with 52 bits. As your number gets closer and closer to exceeding that number of bits, fewer and fewer numbers in a given range can be represented.

For numbers between Math.pow(2, 52) and Math.pow(2, 53), every whole number can be represented. ie:

Math.pow(2, 52) === Math.pow(2, 52) + 0.5

For numbers between Math.pow(2, 53) and Math.pow(2, 54) (which is where 10101010101010100 lies), every second whole number can be represented, followed by every fourth whole number, and so on, as the powers of your range grow.

console.log('2^52 === 2^52 + 0.5 :', 
  Math.pow(2, 52) === Math.pow(2, 52) + 0.5);
  
console.log('2^53 === 2^53 + 1   :', 
  Math.pow(2, 53) === Math.pow(2, 53) + 1);

Upvotes: 3

Related Questions