'How is the parseInt in JavaScript defined to handle large "numbers" - is there an ECMA leak? I got a wow here

The problem: JavaScript returns 20160107190308484 for parseInt("20160107190308485")

Not the question: I do not need a workaround; I got one.

Not the question II: I do not need an explanation why this can happen, and how numbers are stored and so on.

How are numbers as input for parseInt defined? Why do I get a wrong result, not a NaN?

I only find in documentation how parseInt handles literals and so on, that only the first numbers are interpreted and ...

As W3C or MDN

Note: Only the first number in the string is returned!

Note: Leading and trailing spaces are allowed.

Note: If the first character cannot be converted to a number, parseInt() returns NaN.

I can't find anything that says "123456789202232334234212312311" is not a "number". And nothing like "a number must be in the range of -BIGINT .. +BIGINT or so. And I could not find a hint for errors thrown.

I just get 20160107190308484 for "20160107190308485" (two browsers tested) and other pairs like:

   20160107155044520, 20160107155044522
   20160107002720970, 20160107002720967
   20160107000953860, 20160107000953859

For me this feels like a hole in ECMA.

Is there a number defined that is allowed as input for parseInt?


For those who are interested in "how came?":

I stumbled over that problem with a small logic, that converts classes and ids into an object holding the information like

class="book240 lang-en" id="book240page2212"

converting to an object like:

{
    book: 240
    page: 2212
    lang: "en"
}

Notice, that INTs are numbers, not strings.

Therefore I have a loop that makes that generic:

for n in some_regexp_check_names
# m hold a Regexp result arg[1] is the interest:

    nr = parseInt(m[1])    # Make it a number

    #--------- Here the funny fault
    if  nr > 0          # Check if number & > 0 all my ids are > 0
        out_obj[n]=nr   # Take the number
    else
        out_obj[n]=m[1] # Take the string as is

All this is nice and is working with "real strings" and "real (int) ids", and then I had a situation where dynamically semi uuids out of datetime where created: "temp-2016-01-07-19-03-08.485" - and still all fine, but I had the idea to remove all constant chars from this (i.e. temp-.) and BANG, because the string "20160107190308485" gives 20160107190308484 as parseInt.

And it took me only ~3 hours to find that error.



Solution 1:[1]

Although Bergis answer is correct, I want to tell what my real mistake was:

Don't think of parseInt of a function, that parses into an INTeger like known from C as 16, 32 or 64 bit value. It parse the number as long as there are valid digits, so if the number is to big (does not fit exactly into eg 64 bit), you dont get an error, you just get a rounded value like working with float. If you want to be on the safe side: check the result against Number.MAX_SAFE_INTEGER.

Solution 2:[2]

The maximum integer value in JavaScript is 2^53 == 9 007 199 254 740 992. This is because Numbers are stored as floating point is a 52 bit mantissa.

Read more: http://web.archive.org/web/20161117214618/http://bjola.ca/coding/largest-integer-in-javascript/

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 halfbit
Solution 2 kiranvj