admin管理员组文章数量:1310074
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.
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.
Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Feb 2, 2016 at 2:08 halfbithalfbit 3,9643 gold badges35 silver badges49 bronze badges 5- 1 The max safe integer for javascript is generally 2^53 (9007199254740991), and you seem to be way over that. – adeneo Commented Feb 2, 2016 at 2:11
- @adeneo: so it should get NaN, - thats my question! - I never thougth of "20160107190308484 " beeing a number – halfbit Commented Feb 2, 2016 at 2:14
- 1 Well, no, it's the max safe number, you can go higher, but you lose precisicion because of mon issues with floating point precision etc, and there's no telling what you'd get back, at 2^53 you start getting approximations instead, that's why 2^53 - 1 is generally considered safe, it's the number before 2^53 – adeneo Commented Feb 2, 2016 at 2:17
-
@halfbit: Well, it's not a number, it's a string.
parseInt
makes it into one. – Bergi Commented Feb 2, 2016 at 2:26 - @Bergi: :-p - yes kill me with my arguments – halfbit Commented Feb 2, 2016 at 2:31
3 Answers
Reset to default 4How are numbers as input for parseInt defined?
I think it's pretty clearly defined in the spec (§18.2.5):
Let mathInt be the mathematical integer value that is represented by Z in radix-R notation, using the letters A-Z and a-z for digits with values 10 through 35. (However, if R is 10 and Z contains more than 20 significant digits, every significant digit after the 20th may be replaced by a 0 digit, at the option of the implementation; and if R is not 2, 4, 8, 10, 16, or 32, then mathInt may be an implementation-dependent approximation to the mathematical integer value that is represented by Z in radix-R notation.)
Let number be the Number value for mathInt.
For that last step, the section for the Number type (§6.1.6) specifies:
In this specification, the phrase “the Number value for x” where x represents an exact nonzero real mathematical quantity (which might even be an irrational number such as π) means a Number value chosen in the following manner. Consider the set of all finite values of the Number type, with −0 removed and with two additional values added to it that are not representable in the Number type, namely 21024 (which is +1 × 253 × 2971) and −21024 (which is −1 × 253 × 2971). Choose the member of this set that is closest in value to x. If two values of the set are equally close, then the one with an even significand is chosen; for this purpose, the two extra values 21024 and −21024 are considered to have even significands. Finally, if 21024 was chosen, replace it with +∞; if −21024 was chosen, replace it with −∞; if +0 was chosen, replace it with −0 if and only if x is less than zero; any other chosen value is used unchanged. The result is the Number value for x. (This procedure corresponds exactly to the behaviour of the IEEE 754-2008 “round to nearest, ties to even” mode.)
Why do I get a wrong result not a NaN?
You get a rounded result (with the maximum precision available in that range) - and there's nothing wrong with that, your input is a valid number, not NaN
.
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
.
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/web/20161117214618/http://bjola.ca/coding/largest-integer-in-javascript/
本文标签:
版权声明:本文标题:How is the parseInt in JavaScript defined to handle large "numbers" - is there an ECMA leak? I got a wow here 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741855233a2401303.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论