¿Por qué parseInt (1/0, 19) devuelve 18?

853

Tengo un problema molesto en JavaScript .

> parseInt(1 / 0, 19)
> 18

¿Por qué vuelve la parseIntfunción 18?

cebor
fuente
3
Interesante. Pero, ¿por qué es un problema molesto para ti? ¿Tienes que manejar Infinity de otras maneras? Si es así, un ifpodría ayudar.
Thilo
254
¡¿Qué demonios estabas haciendo que requiere trabajar con números de base 19 O división por cero ?!
Jack M
19
Cuando se confunda acerca de JS, solo regrese a esta cita y recuerde que todo el maldito lenguaje fue diseñado e implementado en menos de 10 días (según la persona que lo hizo).
tylerl
32
De las preguntas frecuentes: "Solo debe hacer preguntas prácticas y que respondan en función de los problemas reales que enfrenta". En realidad, este no es un "problema molesto" al que te enfrentas, es un ejemplo poco realista que ha estado flotando en Internet para siempre .
Jeremy Banks
2
Python hace lo mismo: int ('I', 19) == 18
oberhamsi

Respuestas:

1292

El resultado de 1/0es Infinity.

parseInttrata su primer argumento como una cadena, lo que significa que primero Infinity.toString()se llama, produciendo la cadena "Infinity". Por lo tanto, funciona igual que si le pidiera que se convirtiera "Infinity"en base 19 a decimal.

Aquí están los dígitos en base 19 junto con sus valores decimales:

Base 19   Base 10 (decimal)
---------------------------
   0            0
   1            1
   2            2
   3            3
   4            4
   5            5
   6            6
   7            7
   8            8
   9            9
   a            10
   b            11
   c            12
   d            13
   e            14
   f            15
   g            16
   h            17
   i            18

Lo que sucede después es que parseIntescanea la entrada "Infinity"para encontrar qué parte de ella se puede analizar y se detiene después de aceptar la primera I(porque nno es un dígito válido en la base 19).

Por lo tanto, se comporta como si hubiera llamado parseInt("I", 19), que se convierte al 18 decimal según la tabla anterior.

Jon
fuente
32
@mithunsatheesh Intenta parseInt('Infini',24).
Supr
112
@mithunsatheesh: Porque en la base 24 ntambién es un dígito válido, por lo que en realidad termina haciendo parseInt("Infini", 24).
Jon
36
Por qué alguien quiere 'programar' en un lenguaje que se comporta así está más allá de mí.
Frans Bouma
45
@FransBouma: JS es hermosa a su manera. Y realmente, ninguna parte de lo que sucede aquí no es razonable en un lenguaje dinámico.
Jon
59
@ Jon: este artefacto no es el resultado de un lenguaje dinámico; Es el resultado de una escritura floja. En un lenguaje dinámico estrictamente tipado, la conversión implícita de Infinito (flotante) a "Infinito" (cadena) no sucedería, para evitar este tipo de tonterías.
Mentira Ryan
225

Aquí está la secuencia de eventos:

  • 1/0 evalúa a Infinity
  • parseIntlee Infinityy felizmente señala que Ies 18 en base 19
  • parseInt ignora el resto de la cadena, ya que no se puede convertir.

Tenga en cuenta que obtendría un resultado para cualquier base >= 19, pero no para las bases por debajo de eso. Para las bases >= 24, obtendrás un resultado mayor, ya que se nconvierte en un dígito válido en ese punto.

Craig Citro
fuente
@Thilo BTW, ¿cuál sería la razón, por qué podría detenerse en 19, si la base es mayor? ¿Sabes cuál es la base más grande que JS puede interpretar?
Arnthor
44
@Nordvind La base más grande que parseIntse aceptará es 36, ya que hay 26 letras en el alfabeto inglés, y la convención es usar dígitos y luego letras como el conjunto de dígitos válidos en la base dada.
Craig Citro
44
En el punto # 2, ¿puedo sugerir cambiar Infinitya "Infinity"...
CJBS
38

Para agregar a las respuestas anteriores:

parseInt está destinado a analizar cadenas en números (la pista está en el nombre). En su situación, no desea realizar ningún análisis ya que 1/0 ya es un número, por lo que es una elección extraña de función. Si tiene un número (lo que tiene) y desea convertirlo a una base en particular, debe usar toString con una raíz .

var num = 1 / 0;
var numInBase19 = num.toString(19); // returns the string "Infinity"
Kybernetikos
fuente
13

Para agregar a las respuestas anteriores

parseInt(1/0,19) es equivalente a parseInt("Infinity",19)

Dentro de la base 19 números 0-9y A-I (or a-i)son números válidos. Entonces, desde el "Infinito" toma Ide la base 19 y se convierte en la base 10 que se convierte en 18 Luego, trata de tomar el siguiente carácter, es decir, nque no está presente en la base 19, por lo que descarta los siguientes caracteres (según el comportamiento de JavaScript de convertir una cadena a un número )

Entonces, si escribe parseInt("Infinity",19)OR parseInt("I",19)O parseInt("i",19)el resultado será el mismo, es decir 18.

Ahora, si escribes parseInt("I0",19)el resultado será 342 como I X 19 (the base)^1 + 0 X 19^0 = 18 X 19^1 + 0 X 19^0= 18 X 19 + 0 X 1 =342

Del mismo modo, parseInt("I11",19)dará lugar a6518

es decir

  18 X 19^2  +   1 X 19^1   +  1 X 19^0
= 18 X 19^2  +   1 X 19^1   +  1 X 19^0
= 18 X 361   +   1 X 19     +  1 X 1
= 6498  +  19  +  1
= 6518
Soy papá
fuente