javascript - statement - ¿Por qué typeof NaN devuelve ''número''?
nan value javascript (20)
Bueno, NaN
sigue siendo un tipo numérico, a pesar de que en realidad representa Not-A-Number :-)
NaN
solo significa que el valor específico no se puede representar dentro de las limitaciones del tipo numérico (aunque podría decirse que todos los números deben redondearse para ajustarse, pero NaN
es un caso especial).
Un NaN
específico no se considera igual a otro NaN
porque pueden ser valores diferentes. Sin embargo, NaN
sigue siendo un tipo de número, al igual que 2718 o 31415.
En cuanto a su pregunta actualizada para explicar en términos sencillos:
Una comparación con un NaN siempre devuelve un resultado desordenado incluso cuando se compara consigo mismo. Los predicados de comparación son de señalización o de no señalización, las versiones de señalización señalan una excepción no válida para tales comparaciones. Los predicados de igualdad y desigualdad no son de señalización, por lo que x = x return false se puede usar para probar si x es un NaN silencioso.
Todo lo que esto significa es (dividido en partes):
Una comparación con un NaN siempre devuelve un resultado desordenado incluso cuando se compara consigo mismo.
Básicamente, un NaN
no es igual a ningún otro número, incluido otro NaN
, e incluso se incluye a sí mismo .
Los predicados de comparación son de señalización o de no señalización, las versiones de señalización señalan una excepción no válida para tales comparaciones.
Intentar hacer operaciones de comparación (menor que, mayor que, etc.) entre un NaN
y otro número puede dar como resultado una excepción lanzada (señalización) o simplemente obtener como resultado el resultado falso (sin señalización o silencioso).
Los predicados de igualdad y desigualdad no son de señalización, por lo que x = x return false se puede usar para probar si x es un NaN silencioso.
Las pruebas de igualdad (igual a, no igual a) nunca se señalizan, por lo que su uso no provocará una excepción. Si tiene un número regular x
, entonces x == x
siempre será verdadero. Si x
es un NaN
, entonces x == x
siempre será falso. Le está dando una forma de detectar NaN
fácilmente (silenciosamente).
Solo por curiosidad.
No parece muy lógico que el tipo de typeof NaN
sea el número. Al igual que NaN === NaN
o NaN == NaN
devuelve falso, por cierto. ¿Es esta una de las peculiaridades de javascript, o habría una razón para esto?
Editar: gracias por tus respuestas. Sin embargo, no es algo fácil de entender. Leyendo las respuestas y el wiki entendí más, pero aún así, una oración como
Una comparación con un NaN siempre devuelve un resultado desordenado incluso cuando se compara consigo mismo. Los predicados de comparación son de señalización o de no señalización, las versiones de señalización señalan una excepción no válida para tales comparaciones. Los predicados de igualdad y desigualdad no son de señalización, por lo que x = x return false se puede usar para probar si x es un NaN silencioso.
solo me da vueltas la cabeza. Si alguien puede traducir esto en lenguaje legible humano (en oposición a, digamos, matemático), le estaría agradecido.
El estándar ECMAScript (JavaScript) especifica que los Numbers
son flotantes IEEE 754 , que incluyen NaN
como valor posible.
ECMA 262 5e Sección 4.3.19 : valor numérico
valor primitivo correspondiente a un valor IEEE 754 de formato binario de 64 bits de doble precisión.
ECMA 262 5e Sección 4.3.23 : NaN
Valor numérico que es un valor IEEE 754 "No es un número".
IEEE 754 en Wikipedia
El Estándar IEEE para Aritmética de Puntos Flotantes es un estándar técnico establecido por el Instituto de Ingenieros Eléctricos y Electrónicos y el estándar más ampliamente utilizado para el cálculo de coma flotante [...]
El estándar define
- formatos aritméticos : conjuntos de datos en coma flotante binarios y decimales, que consisten en números finitos (incluidos ceros con signo y números subnormales), infinitos y valores especiales "no un número" (NaN)
[...]
El valor NaN es realmente Number.NaN, por lo tanto, cuando pregunta si es un número, dirá que sí. Hizo lo correcto al usar la llamada a isNaN ().
Para información, NaN también puede ser devuelto por operaciones en Números que no están definidos como divisiones por cero o raíz cuadrada de un número negativo.
Es un valor especial del tipo de número como POSITIVE_INFINITY
¿Por qué? Por diseño
Esto es simplemente porque NaN
es una propiedad del objeto Number en JS, no tiene nada que ver con que sea un número.
Javascript tiene solo un tipo de datos numéricos, que es el flotante estándar de doble precisión de 64 bits. Todo es un doble NaN es un valor especial de doble, pero es un doble, no obstante.
Todo lo que parseInt
hace es "convertir" su cadena en un tipo de datos numéricos, por lo que el resultado es siempre "número"; solo si la cadena original no fue parseable, su valor será NaN.
Javascript usa NaN para representar cualquier cosa que encuentre que no pueda ser representada de otra manera según sus especificaciones. No significa que no es un número. Es la forma más fácil de describir el encuentro. NaN significa que este o un objeto que hace referencia a él no puede ser representado de ninguna otra forma por javascript. Para todos los propósitos prácticos, es "desconocido". Al ser "desconocido" no puede decirte de qué se trata ni si es él mismo. Ni siquiera es el objeto al que está asignado. Solo puede decirle lo que no es, y la no-nada o la nada solo pueden describirse matemáticamente en un lenguaje de programación. Dado que las matemáticas se refieren a los números, javascript representa la nada como NaN. Eso no quiere decir que no sea un número. Significa que no podemos leerlo de otra manera que tenga sentido. Es por eso que ni siquiera puede igualarse a sí mismo. Porque no es así.
La mejor manera de pensar en NAN es que no es un número conocido . Es por eso que NAN! = NAN porque cada valor de NAN representa algún número desconocido único. Los NAN son necesarios porque los números de coma flotante tienen un rango limitado de valores. En algunos casos, el redondeo ocurre cuando los bits más bajos se pierden, lo que lleva a lo que parece ser una tontería como 1.0 / 11 * 11! = 1.0. Los valores realmente grandes que son mayores son NAN con infinito como un ejemplo perfecto.
Dado que solo tenemos diez dedos, cualquier intento de mostrar valores superiores a 10 es imposible, lo que significa que dichos valores deben ser NAN porque hemos perdido el valor verdadero de este valor mayor a 10. Lo mismo es cierto para los valores de coma flotante, donde el valor excede los límites de lo que se puede mantener en un flotador.
NaN es un valor de coma flotante válido ( http://en.wikipedia.org/wiki/NaN )
y NaN === NaN es falso porque no son necesariamente el mismo no número
NaN sigue siendo un tipo numérico, pero representa un valor que no podría representar un número válido.
Podríamos argumentar que NaN es un objeto de caso especial. En este caso, el objeto de NaN representa un número que no tiene sentido matemático. Hay algunos otros objetos de casos especiales en matemáticas como INFINITE y demás.
Todavía puede hacer algunos cálculos con él, pero eso producirá comportamientos extraños.
Más información aquí: http://www.concentric.net/~ttwang/tech/javafloat.htm (basado en java, no javascript)
Porque NaN es un tipo de datos numéricos.
Si isNumeric
jQuery, prefiero isNumeric
verificar el tipo:
console.log($.isNumeric(NaN)); // returns false
console.log($.type(NaN)); // returns number
Significa que no es un número. No es una peculiaridad del javascript, sino del principio común de la informática.
De http://en.wikipedia.org/wiki/NaN :
Hay tres tipos de operaciones que devuelven NaN:
Operaciones con un NaN como al menos un operando
Formas indeterminadas
- Las divisiones 0/0, ∞ / ∞, ∞ / -∞, -∞ / ∞, y -∞ / -∞
- Las multiplicaciones 0 × ∞ y 0 × -∞
- El poder 1 ^ ∞
- Las adiciones ∞ + (-∞), (-∞) + ∞ y restas equivalentes.
Operaciones reales con resultados complejos:
- La raíz cuadrada de un número negativo
- El logaritmo de un número negativo
- La tangente de un múltiplo impar de 90 grados (o π / 2 radianes)
- El seno o coseno inverso de un número que es menor que -1 o mayor que +1.
Todos estos valores pueden no ser iguales. Una prueba simple para un NaN es probar el value == value
es falso.
Tienes que amar Javascript. Tiene algunos pequeños caprichos interesantes.
La mayoría de esos caprichos pueden explicarse si te paras a resolverlos lógicamente, o si conoces un poco sobre la teoría de números, pero aún así te pueden atrapar si no los conoces.
Por cierto, recomiendo leer el resto de http://wtfjs.com/ - ¡hay muchos más caprichos interesantes que éste!
Un mejor nombre para NaN
, describiendo su significado de manera más precisa y menos confusa, sería una excepción numérica . Es realmente otro tipo de objeto de excepción disfrazado de tipo primitivo (por el diseño del lenguaje), donde al mismo tiempo no se trata como primitivo en su falsa autocomparación. De ahí la confusión. Y mientras el lenguaje "no se decida" a elegir entre el objeto de excepción apropiado y el número primitivo , la confusión se mantendrá.
La infame falta de igualdad de NaN
consigo misma, ambos ==
y ===
es una manifestación del diseño confuso que obliga a este objeto de excepción a ser un tipo primitivo. Esto rompe el principio fundamental de que un primitivo está determinado de manera única por su valor . Si se prefiere que NaN
sea visto como una excepción (de la cual puede haber diferentes tipos), entonces no se debe "vender" como primitivo. Y si se quiere ser primitivo, ese principio debe mantenerse. Mientras esté roto, como lo tenemos en JavaScript, y realmente no podemos decidir entre los dos, la confusión que lleva a una carga cognitiva innecesaria para todos los involucrados permanecerá. Lo cual, sin embargo, es realmente fácil de solucionar simplemente haciendo la elección entre los dos:
- o bien convierten a
NaN
un objeto de excepción especial que contiene la información útil sobre cómo surgió la excepción, en lugar de descartar esa información como lo que se implementa actualmente, lo que lleva a un código más difícil de depurar; - o hacer
NaN
una entidad delnumber
tipo primitivo (que podría llamarse "numérico" de manera menos confusa), en cuyo caso debería ser igual a sí mismo y no puede contener ninguna otra información; este último es claramente una elección inferior.
La única ventaja concebible de forzar NaN
en el tipo de number
es poder devolverlo a cualquier expresión numérica. Lo cual, sin embargo, hace que sea una elección frágil, porque el resultado de cualquier expresión numérica que contenga NaN
será NaN
o conducirá a resultados impredecibles, como NaN < 0
evaluando a false
, es decir, devolviendo boolean
lugar de mantener la excepción.
E incluso si "las cosas son como son", nada nos impide hacer esa distinción clara para nosotros mismos, para ayudar a que nuestro código sea más predecible y más fácil de depurar. En la práctica, eso significa identificar esas excepciones y tratarlas como excepciones. Lo cual, desafortunadamente, significa más código pero, con suerte, será mitigado por herramientas como TypeScript of Flowtype.
Y luego tenemos el desordenado silencio vs ruidoso alias señalización NaN
distinción . Lo que realmente se trata de cómo se manejan las excepciones, no las excepciones en sí, y nada diferente de otras excepciones.
Del mismo modo, Infinity
y +Infinity
son elementos de tipo numérico que surgen en la extensión de la línea real, pero no son números reales. Matemáticamente, pueden representarse mediante secuencias de números reales que convergen hacia +
o -Infinity
.
NaN != NaN
porque no son necesarios el MISMO no número. Por lo tanto, tiene mucho sentido ... También por qué los flotadores tienen ambos +0.00 y -0.00 que no son lo mismo. El redondeo puede hacer que en realidad no sean cero.
En cuanto a typeof, eso depende del idioma. Y la mayoría de los idiomas dirán que NaN es un flotante, doble o número dependiendo de cómo lo clasifiquen ... No conozco ningún idioma que diga que es un tipo desconocido o nulo.
NaN
es un número desde un punto de vista de tipo, pero no es un número normal como 1, 2 o 329131. El nombre "No es un número" se refiere al hecho de que el valor representado es especial y se trata del dominio de especificación de formato IEEE. no dominio de lenguaje javascript.
NaN
significa http://en.wikipedia.org/wiki/NaN . Es un valor de tipos de datos numéricos (generalmente, tipos de punto flotante, pero no siempre) que representa el resultado de una operación no válida como dividir por cero.
Aunque sus nombres dicen que no es un número, el tipo de datos utilizado para mantenerlo es un tipo numérico. Entonces, en JavaScript, preguntar por el tipo de datos de NaN
devolverá el number
(como lo demuestra claramente la alert(typeof(NaN))
).
typeof NaN
devuelve ''number''
porque:
La especificación de ECMAScript dice que el tipo de número incluye NaN:
conjunto de todos los valores numéricos posibles, incluidos los valores especiales "No-un-Número" (NaN), infinito positivo e infinito negativo
Así que
typeof
regresa en consecuencia:La producción UnaryExpression :
typeof
UnaryExpression se evalúa de la siguiente manera:- Deje que val sea el resultado de evaluar UnaryExpression .
- Si Type ( val ) es Reference , entonces
- Devuelve una Cadena determinada por Type ( val ) de acuerdo con la Tabla 20.
1.
Table 20 — typeof Operator Results ================================================================== | Type of val | Result | ================================================================== | Undefined | "undefined" | |----------------------------------------------------------------| | Null | "object" | |----------------------------------------------------------------| | Boolean | "boolean" | |----------------------------------------------------------------| | Number | "number" | |----------------------------------------------------------------| | String | "string" | |----------------------------------------------------------------| | Object (native and does | "object" | | not implement [[Call]]) | | |----------------------------------------------------------------| | Object (native or host and | "function" | | does implement [[Call]]) | | |----------------------------------------------------------------| | Object (host and does not | Implementation-defined except may | | implement [[Call]]) | not be "undefined", "boolean", | | | "number", or "string". | ------------------------------------------------------------------
Este comportamiento está de acuerdo con el estándar IEEE para aritmética de coma flotante (IEEE 754) :
valor primitivo correspondiente a un valor binario de formato IEEE 754 de doble precisión de 64 bits
valor numérico que es un valor IEEE 754 "No es un número"
El tipo Número tiene exactamente 18437736874454810627 (es decir, 2 53 -2 64 +3) valores, que representan los valores IEEE 754 de doble precisión de 64 bits como se especifica en el Estándar IEEE para aritmética de coma flotante binario, excepto que el 9007199254740990 ( es decir, 2 53 -2) los valores distintos de "No-un-Número" del Estándar IEEE se representan en ECMAScript como un único valor NaN especial. (Tenga en cuenta que el valor NaN es producido por la expresión del programa
NaN
).