2

In javascript, numbers are represented internally as double-precision floats, meaning there are 53 bits available to represent integer values. There's a Number.MAX_SAFE_INTEGER constant that illustrates this, which is equal to Math.pow(2, 53) - 1. However, in the javascript console, I can type Number.MAX_SAFE_INTEGER + 20 and it will spit out the correct integer value.

How does javascript represent numbers greater than Number.MAX_SAFE_INTEGER internally?

w.brian
  • 16,296
  • 14
  • 69
  • 118
  • 2
    I don't get it, you just answered your own question? – Bergi Feb 15 '19 at 15:54
  • 1
    Try `+ 19` instead. – Bergi Feb 15 '19 at 15:54
  • 2
    https://stackoverflow.com/a/34799443/3684265 – imvain2 Feb 15 '19 at 15:54
  • 2
    I think the important thing here is the word **`SAFE`** – Liam Feb 15 '19 at 15:55
  • I understand that using numbers greater than `Number.MAX_SAFE_INTEGER` isn't safe, so perhaps the better question would be *why* isn't it safe? Is it unsafe because some browsers will coerce to BigInt while others won't (inconsistent implementations)? Or because it will give unreliable results. Based on the comments and the answer now posted, it appears to be the latter. – w.brian Feb 15 '19 at 16:04
  • Yes, unreliable results. Not all integers larger than the MAX_SAFE_INTEGER value can be *accurately* represented in 64-bit floating point, and will be subject to rounding. – Bergi Feb 15 '19 at 16:06
  • @w.brian well, they will be represented reliably wrong – Jonas Wilms Feb 15 '19 at 16:13

1 Answers1

2

Basically floating point numbers are represented as:

 digits * 2 ** movement

digits has 52 bits, movement has 11 bits, and both together form a 64bit number (with 1 sign bit). Now integers can just be represented with movement being 0, then digits contains the 52 bit number, and that can hold up to 2 ** 53 - 1 numbers. Now for larger numbers, you have to use movement, which basically means that you move the digits left or right, and therefore you lose accuracy.

Imagine digits would just take 8 bits

  number     >     digits | movement > result
   // savely represented
  11111111   >  111111111 | 0        > 11111111
  // lost the last 1
  111111111  >  111111111 | 1        > 111111110
   // lost the two last 1s
  1111111111 >  11111111  | 10       > 1111111100
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151