with variable number javascript parseint

javascript - variable - parseint typescript



parseInt(nulo, 24)=== 23... espera, ¿qué? (6)

Está convirtiendo null a la cadena "null" e intentando convertirlo. Para los radixes 0 a 23, no hay números que pueda convertir, por lo que devuelve NaN . En 24, "n" , la letra 14, se agrega al sistema de numeración. En 31, se agrega "u" , la letra 21, y se puede descodificar toda la cadena. En 37 en adelante ya no hay ningún conjunto de numeración válido que pueda generarse y se devuelve NaN.

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

Muy bien, así que estaba jugando con ParseInt para ver cómo maneja los valores que aún no se han inicializado y me topé con esta joya. Lo siguiente sucede para cualquier radix 24 o superior.

parseInt(null, 24) === 23 // evaluates to true

Lo probé en IE, Chrome y Firefox y todos son alertas verdaderos, así que creo que debe estar en la especificación en algún lugar. Una búsqueda rápida en Google no me dio ningún resultado, así que aquí estoy, esperando que alguien pueda explicarlo.

Recuerdo haber escuchado un discurso de Crockford cuando decía typeof null === "object" debido a un descuido que hace que Object y Null tengan un identificador de tipo casi idéntico en la memoria o algo así, pero no puedo encontrar ese video ahora.

Pruébelo: http://jsfiddle.net/robert/txjwP/

Corrección de edición : un radix superior devuelve resultados diferentes, 32 retornos 785077
Edición 2 De zzzzBov: [24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745

tl; dr

Explique por qué parseInt(null, 24) === 23 es una declaración verdadera.


Ignacio Vázquez-Abrams es correcto, pero veamos exactamente cómo funciona ...

Desde 15.1.2.2 parseInt (string , radix) :

Cuando se llama a la función parseInt, se toman los siguientes pasos:

  • Deje que inputString sea ToString (cadena).
  • Sea S una nueva subcadena creada de inputString que consiste en el primer carácter que no es StrWhiteSpaceChar y todos los caracteres que siguen a ese carácter. (En otras palabras, elimine los espacios en blanco iniciales).
  • Que el signo sea 1.
  • Si S no está vacío y el primer carácter de S es un signo menos, deje que el signo sea −1.
  • Si S no está vacío y el primer carácter de S es un signo más + o un signo menos -, elimine el primer carácter de S.
  • Sea R = ToInt32 (radix).
  • Deje que stripPrefix sea verdadero.
  • Si R ≠ 0, entonces a. Si R <2 o R> 36, entonces devuelve NaN. segundo. Si R ≠ 16, deje que stripPrefix sea falso.
  • Si no, R = 0 a. Sea R = 10.
  • Si stripPrefix es verdadero, entonces a. Si la longitud de S es al menos 2 y los dos primeros caracteres de S son “0x” o “0X”, elimine los dos primeros caracteres de S y deje que R = 16.
  • Si S contiene cualquier carácter que no sea un dígito de R de raíz, entonces Z sea la subcadena de S que consta de todos los caracteres antes del primer carácter; de lo contrario, sea Z sea S.
  • Si Z está vacío, devuelve NaN.
  • Sea mathInt el valor entero matemático que está representado por Z en la notación radix-R, usando las letras AZ y az para los dígitos con valores 10 a 35. (Sin embargo, si R es 10 y Z contiene más de 20 dígitos significativos, todos el dígito después del 20 puede ser reemplazado por un dígito 0, a opción de la implementación, y si R no es 2, 4, 8, 10, 16 o 32, entonces mathInt puede ser una aproximación dependiente de la implementación al número entero matemático valor que está representado por Z en notación radix-R)
  • Deje que número sea el valor Número para mathInt.
  • Signo de retorno × número.

NOTA parseInt puede interpretar solo una parte inicial de la cadena como un valor entero; ignora cualquier carácter que no pueda interpretarse como parte de la notación de un entero, y no se da ninguna indicación de que se haya ignorado ninguno de estos caracteres.

Hay dos partes importantes aquí. Me atreví a los dos. En primer lugar, tenemos que averiguar qué es la representación de null de toString . Necesitamos ver la Table 13 — ToString Conversions en la sección 9.8.0 para esa información:

Genial, ahora sabemos que hacer toString(null) produce internamente una cadena ''null'' . Genial, pero ¿cómo maneja exactamente los dígitos (caracteres) que no son válidos dentro del radix proporcionado?

Miramos arriba a 15.1.2.2 y vemos el siguiente comentario:

Si S contiene cualquier carácter que no sea un dígito de R de raíz, entonces Z sea la subcadena de S que consta de todos los caracteres antes del primer carácter; de lo contrario, sea Z sea S.

Eso significa que manejamos todos los dígitos ANTES del radix especificado e ignoramos todo lo demás.

Básicamente, hacer parseInt(null, 23) es lo mismo que parseInt(''null'', 23) . La u hace que se ignoren los dos l (aunque SON parte de la raíz 23). Por lo tanto, solo podemos analizar n , haciendo que toda la declaración sea sinónimo de parseInt(''n'', 23) . :)

De cualquier manera, gran pregunta!


Mozilla nos dice :

La función parseInt convierte su primer argumento en una cadena , la analiza y devuelve un entero o NaN. Si no es NaN, el valor devuelto será la representación entera decimal del primer argumento tomado como un número en el radix especificado (base). Por ejemplo, una raíz de 10 indica la conversión de un número decimal, 8 octales, 16 hexadecimales, etc. Para los radices superiores a 10, las letras del alfabeto indican números mayores que 9. Por ejemplo, para los números hexadecimales (base 16), se utilizan de la A a la F.

En la especificación , 15.1.2.2/1 nos dice que la conversión a cadena se realiza mediante la función ToString , que (según 9.8) produce "null" (no debe confundirse con toString , que produciría "[object Window]" !).

Entonces, consideremos parseInt("null", 24) .

Por supuesto, esto no es una cadena numérica de base 24 en su totalidad, pero "n" es: es decimal 23 .

Ahora, el análisis se detiene después de que se extrae el decimal 23, porque no se encuentra "u" en el sistema base-24:

Si S contiene cualquier carácter que no sea un dígito de R de raíz, entonces Z sea la subcadena de S que consta de todos los caracteres antes del primer carácter; de lo contrario, sea Z sea S. [15.1.2.2/11]

(Y es por esto que parseInt(null, 23) (y radices inferiores) le da NaN lugar de 23: "n" no está en el sistema base-23.)


Supongo que null se convierte en una cadena "null" . Entonces n es 23 en ''base24'' (igual en ''base25'' +), u no es válido en ''base24'', por lo que el resto de la cadena null se ignorará. Es por eso que genera 23 hasta que se convierta en válido en ''base31''.


parseInt usa representación alfanumérica, luego en base-24 "n" es válida, pero "u" no es un carácter válido, entonces parseInt solo analiza el valor "n" ....

parseInt("n",24) -> 23

Como ejemplo, prueba con esto:

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

El resultado será "3".


parseInt( null, 24 ) === 23

Es equivalente a

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

que es equivalente a

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

Los dígitos para la base 24 son 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, ..., n.

La especificación de idioma dice

  1. Si S contiene cualquier carácter que no sea un dígito de R de raíz, entonces Z sea la subcadena de S que consta de todos los caracteres antes del primer carácter; de lo contrario, sea Z sea S.

que es la parte que garantiza que los literales enteros de estilo C como 15L analizan correctamente, por lo que lo anterior es equivalente a

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

"n" es la letra 23 de la lista de dígitos anterior.

QED