[ACCEPTED]-parseInt(null, 24) === 23... wait, what?-parseint

Accepted answer
Score: 243

It's converting null to the string "null" and trying 7 to convert it. For radixes 0 through 23, there 6 are no numerals it can convert, so it returns 5 NaN. At 24, "n", the 14th letter, is added to 4 the numeral system. At 31, "u", the 21st letter, is 3 added and the entire string can be decoded. At 2 37 on there is no longer any valid numeral 1 set that can be generated and NaN is returned.

js> parseInt(null, 36)
1112745

>>> reduce(lambda x, y: x * 36 + y, [(string.digits + string.lowercase).index(x) for x in 'null'])
1112745
Score: 119

Mozilla tells us:

function parseInt converts its first argument to a string, parses it, and returns 25 an integer or NaN. If not NaN, the returned 24 value will be the decimal integer representation 23 of the first argument taken as a number 22 in the specified radix (base). For example, a radix 21 of 10 indicates to convert from a decimal 20 number, 8 octal, 16 hexadecimal, and so 19 on. For radices above 10, the letters 18 of the alphabet indicate numerals greater 17 than 9. For example, for hexadecimal numbers 16 (base 16), A through F are used.

In the spec, 15.1.2.2/1 15 tells us that the conversion to string is 14 performed using the built-in ToString, which (as 13 per 9.8) yields "null" (not to be confused with 12 toString, which would yield "[object Window]"!).

So, let's consider 11 parseInt("null", 24).

Of course, this isn't a base-24 numeric 10 string in entirety, but "n" is: it's 9 decimal 23.

Now, parsing stops after the decimal 23 8 is pulled out, because "u" isn't found in the base-24 7 system:

If S contains any character that 6 is not a radix-R digit, then let Z be 5 the substring of S consisting of all characters 4 before the first such character; otherwise, let 3 Z be S. [15.1.2.2/11]

(And this is why parseInt(null, 23) (and 2 lower radices) gives you NaN rather than 23: "n" is 1 not in the base-23 system.)

Score: 79

Ignacio Vazquez-Abrams is correct, but lets 23 see exactly how it works...

From 15.1.2.2 parseInt (string , radix):

When the parseInt function 22 is called, the following steps are taken:

  • Let inputString be ToString(string).
  • Let S be a newly created substring of inputString consisting of the first character that is not a StrWhiteSpaceChar and all characters following that character. (In other words, remove leading white space.)
  • Let sign be 1.
  • If S is not empty and the first character of S is a minus sign -, let sign be −1.
  • If S is not empty and the first character of S is a plus sign + or a minus sign -, then remove the first character from S.
  • Let R = ToInt32(radix).
  • Let stripPrefix be true.
  • If R ≠ 0, then a. If R < 2 or R > 36, then return NaN. b. If R ≠ 16, let stripPrefix be false.
  • Else, R = 0 a. Let R = 10.
  • If stripPrefix is true, then a. If the length of S is at least 2 and the first two characters of S are either “0x” or “0X”, then remove the first two characters from S and let R = 16.
  • If S contains any character that is not a radix-R digit, then let Z be the substring of S consisting of all characters before the first such character; otherwise, let Z be S.
  • If Z is empty, return NaN.
  • 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.
  • Return sign × number.

NOTE parseInt may interpret only a leading portion of string as an integer value; it ignores any characters that cannot be interpreted as part of the notation of an integer, and no indication is given that any such characters were ignored.

There 21 are two important parts here. I bolded both 20 of them. So first of all, we have to find 19 out what the toString representation of null is. We 18 need to look at Table 13 — ToString Conversions in section 9.8.0 for that 17 information:

enter image description here

Great, so now we know that doing 16 toString(null) internally yields a 'null' string. Great, but 15 how exactly does it handle digits (characters) that 14 aren't valid within the radix provided?

We 13 look above to 15.1.2.2 and we see the following 12 remark:

If S contains any character that 11 is not a radix-R digit, then let Z be 10 the substring of S consisting of all characters 9 before the first such character; otherwise, let 8 Z be S.

That means that we handle all digits 7 PRIOR to the specified radix and ignore 6 everything else.

Basically, doing parseInt(null, 23) is the 5 same thing as parseInt('null', 23). The u causes the two l's to 4 be ignored (even though they ARE part of 3 the radix 23). Therefore, we only can only 2 parse n, making the entire statement synonymous 1 to parseInt('n', 23). :)

Either way, great question!

Score: 34
parseInt( null, 24 ) === 23

Is equivalent to

parseInt( String(null), 24 ) === 23

which is equivalent to

parseInt( "null", 24 ) === 23

The 6 digits for base 24 are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, ..., n.

The 5 language spec says

  1. If S contains any character that is not a radix-R digit, then let Z be the substring of S consisting of all characters before the first such character; otherwise, let Z be S.

which is the part that 4 ensures that C-style integer literals like 3 15L parse properly, so the above is equivalent 2 to

parseInt( "n", 24 ) === 23

"n" is the 23-rd letter of the digit list 1 above.

Q.E.D.

Score: 16

I guess null gets converted to a string "null". So 4 n is actually 23 in 'base24' (same in 'base25'+), u is 3 invalid in 'base24' so the rest of the string 2 null will be ignored. That's why it outputs 1 23 until u will become valid in 'base31'.

Score: 7

parseInt uses alphanumeric representation, then 4 in base-24 "n" is valid, but "u" is invalid 3 character, then parseInt only parses the 2 value "n"....

parseInt("n",24) -> 23

as an example, try with this:

alert(parseInt("3x", 24))

The 1 result will be "3".

More Related questions