4

I thought the max integer value for javascript was 2^53, but when I do the following:

 parseInt(Math.pow(2, 53)) + 10

I correctly get 9007199254741002

 (= 9007199254740992 + 10)

Why is that? I want to use a bigint.js library only if the number is greater than or equal to the max integer allowed.

2 Answers2

3

9007199254740992 is the max integer value in JavaScript before you start running into loss of precision issues. Consider this following:

> Math.pow(2, 53) + 1
9007199254740992
> Math.pow(2, 53) + 2
9007199254740994
> Math.pow(2, 53) + 3
9007199254740996
> Math.pow(2, 53) + 4

As can be seen, the resulting value is not accurate in all cases. This is a limitation of floating point numbers, resulting from having only 53 bits dedicated to the coefficient. Once you exceed the range that can be represented with 53 bits plus a sign bit, the floating point representation will become increasingly hit or miss as the value rises.

jmar777
  • 38,796
  • 11
  • 66
  • 64
2

JavaScript uses IEEE-754 double-precision numbers, which have roughly 15 digits of decimal precision, but a huge range. In this format, the whole numbers -2^53 through 2^53 can all be reliably represented (this is the precision of the significand of the format). Outside those limits, some whole numbers can be represented but others cannot. E.g., outside that range, there are whole-number gaps.

For instance, double-precision numbers can represent 9,007,199,254,740,992 (2^53) and 9,007,199,254,740,994 (2^53 + 2), but not 9,007,199,254,740,993 (2^53 + 1):

Example console session:

> 9007199254740992
9007199254740992
> 9007199254740992 + 1
9007199254740992
> 9007199254740992 + 2
9007199254740994

Note the second of those. That's not a typo.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • You should mention that all integers up to 2^53 are represented precisely in JavaScript. Only after that value the precision for integers drops. – Tibos Apr 03 '14 at 13:08
  • Interesting.. So I guess I just check if the integer is smaller than 9007199254740992, then I use internal math (if I only do division / substraction and %). If it's higher than that number, then I use a bigint.js library? –  Apr 03 '14 at 13:09
  • @Wesley: Yes, I believe 2^53 is the maximum *safe* value. – T.J. Crowder Apr 03 '14 at 13:10
  • OK, one more q, should I also check for isNaN ? I assume once you have a really big integer it would be represented as such? So then my if would fail. Is it possible that it would show up as 0 too? –  Apr 03 '14 at 13:12
  • @Wesley: I haven't explored the boundaries of this, but I would expect you to get `Infinity` or just a really, really imprecise value, rather than `NaN`, if you exceed the overall range of the format. – T.J. Crowder Apr 03 '14 at 13:17
  • @Wesley Be careful, though. You're not necessarily free from floating point precision issues just because you're using values that are less than the max int. – jmar777 Apr 03 '14 at 13:18
  • @Wesley You'll never get `NaN` due to a value being too large or too lossy from a floating point perspective. – jmar777 Apr 03 '14 at 13:19
  • @T.J.Crowder I believe that all values `>= Number.MAX_VALUE` are effectively represented as `Number.MAX_VALUE`. E.g., `Number.MAX_VALUE + === Number.MAX-VALUE`. – jmar777 Apr 03 '14 at 13:23
  • @jmar777: It's not the representation we have to worry about, but what the defined result of a calculation is. For instance, `Number.MAX_VALUE * 2` yields `Infinity`. That's defined by the ECMAScript spec: http://www.ecma-international.org/ecma-262/5.1/#sec-11.5.1 – T.J. Crowder Apr 03 '14 at 13:25
  • What do you mean by not being free from floating point precision errors if I stay within 2^53? Do you have an example of how it can go wrong? –  Apr 03 '14 at 13:29
  • 1
    @Wesley: The key there is *floating point*. If you stick with whole numbers, and none of your calculations results in a fractional number (so, you aren't dividing, only adding, subtracting, or mulitplying), you can rely on whole number results. But imprecisions outside of whole numbers are all over the place. The classic example is `0.1 + 0.2`, which yields `0.30000000000000004`. – T.J. Crowder Apr 03 '14 at 13:31
  • Well, my use case is a bitcoin like system. You have integers representing "satoshis", which is 10^-8, so I need to do these two things: var fractionalPart = amount % 100000000; amount = Math.floor(amount / 100000000); Nothing else. Will this work correctly? –  Apr 03 '14 at 13:34
  • @T.J.Crowder That's really interesting. At least in V8, something like `Number.MAX_VALUE + 9999999999999 === Number.MAX_VALUE`. But like you said, `* 2` does yield `Infinity`. – jmar777 Apr 03 '14 at 14:14
  • 1
    @jmar777: Yeah. Even `Number.MAX_VALUE + 1e+291` equals `Number.MAX_VALUE`. But `Number.MAX_VALUE + 1e+292` is `Infinity`. – T.J. Crowder Apr 03 '14 at 14:33