He leído un artículo sobre JavaScript parseInt
, que tenía esta pregunta:
parseInt(0.5); // => 0 parseInt(0.05); // => 0 parseInt(0.005); // => 0 parseInt(0.0005); // => 0 parseInt(0.00005); // => 0 parseInt(0.000005); // => 0 parseInt(0.0000005); // => 5
¿Por qué está pasando esto?
Lo busqué en el estándar ecmascript y vi esto:
El primer paso es converting the input to `string` if it is not
:
19.2.5 parseInt (cadena, raíz)
La función parseInt es el objeto intrínseco %parseInt%. Cuando se llama a la función parseInt, se toman los siguientes pasos:
Let inputString be ? ToString(string).
- Seamos ! TrimString (cadena de entrada, inicio).
...
Entonces, verifiqué los valores basados en cadenas usando la función String
para ver cuál es el resultado de cada uno de ellos:
String(0.5); // => '0.5' String(0.05); // => '0.05' String(0.005); // => '0.005' String(0.0005); // => '0.0005' String(0.00005); // => '0.00005' String(0.000005); // => '0.000005' String(0.0000005); // => '5e-7'
Entonces, significa que cuando usamos parseInt(0.0000005)
, es igual a parseInt('5e-7')
y se basa en la definición:
parseInt
puede interpretaronly a leading portion of string as an integer value
; ignora cualquier unidad de código que no se pueda interpretar como parte de la notación de un número entero, y no se da ninguna indicación de que se hayan ignorado tales unidades de código.
Entonces, la respuesta devolverá 5
solo porque es el único carácter que es un número hasta que no es un carácter e
, por lo que el resto e-7
se descartará.
(Este es más un comentario largo que una respuesta competitiva).
La conversión no deseada que conduce a este efecto extraño solo ocurre cuando se pasa el valor a parseInt
como un tipo de número; en este caso, parece que el compilador (o el intérprete o lo que sea que controle JS) convierte automáticamente el número en una cadena para usted, como el tipo de cadena es el tipo esperado del parámetro de función
Esa función de conversión de número a cadena, desafortunadamente, prefiere el formato de número de ingeniería cuando, de lo contrario, sería demasiado largo.
Además, la conversión puede conducir a la pérdida de precisión, que es algo que todo programador debe tener en cuenta cuando se trata de números decimales (no enteros).
Si, en cambio, recuerda colocar el valor que se va a analizar en una cadena usted mismo, no obtendrá resultados tan inesperados:
let n = '0.0000005'; console.log(parseInt(n))
Imprimirá 0 como se desee.
Lecciones aprendidas:
parseInt
y funciones similares que no le permiten saber si la cadena que se va a analizar tiene datos adicionales que no se ajustan. Por ejemplo, el análisis int "x" o "1x" debería indicarle que este no es un número int adecuado. En este sentido, parseInt
exhibe un mal comportamiento al ignorar los datos adicionales en la cadena y no informarnos. Una buena función de analizador le dice dónde se detuvo (para que pueda verificar si queda basura) o falla cuando encuentra datos inesperados.¡Respete el tipo de datos!
En la consola de Chrome:
analizarInt("0.5");
0
analizarInt("0.05");
0
analizarInt("0.005");
0
analizarInt("0.0005");
0
analizarInt("0.00005");
0
analizarInt("0.000005");
0
analizarInt("0.0000005");
0
analizarInt("0.00000005");
0
analizarInt("0.000000005");
0