En informática , NaN ( / n æ n / ), que significa Not a Number (No es un número) , es un valor particular de un tipo de datos numérico (a menudo un número de punto flotante ) que no está definido como un número, como el resultado de 0/0 . El uso sistemático de NaN fue introducido por el estándar de punto flotante IEEE 754 en 1985, junto con la representación de otras cantidades no finitas como los infinitos .
En matemáticas , el resultado de 0/0 normalmente no se define como un número [a] y, por lo tanto, puede representarse mediante NaN en los sistemas informáticos.
La raíz cuadrada de un número negativo no es un número real y, por lo tanto, también se representa mediante NaN en los sistemas informáticos compatibles. Los NaN también se pueden utilizar para representar valores faltantes en los cálculos. [1] [2]
Se proporcionan dos tipos distintos de NaN, denominados NaN silenciosos y NaN de señalización . Los NaN silenciosos se utilizan para propagar errores resultantes de operaciones o valores no válidos. Los NaN de señalización pueden admitir funciones avanzadas, como la combinación de cálculos numéricos y simbólicos u otras extensiones de la aritmética básica de punto flotante.
En los cálculos de punto flotante, NaN no es lo mismo que infinito , aunque ambos se manejan típicamente como casos especiales en representaciones de punto flotante de números reales, así como en operaciones de punto flotante. Una operación no válida tampoco es lo mismo que un desbordamiento aritmético (que devolvería un infinito o el número finito más grande en magnitud) o un desbordamiento aritmético por debajo de su valor (que devolvería el número normal más pequeño en magnitud, un número subnormal o cero ).
Los NaN IEEE 754 se codifican con el campo de exponente lleno de unos (como valores infinitos) y algún número distinto de cero en el campo de mantisa (para hacerlos distintos de los valores infinitos); esto permite la definición de múltiples valores NaN distintos, dependiendo de qué bits se establezcan en el campo de mantisa, pero también del valor del bit de signo principal (pero no se requiere que las aplicaciones proporcionen una semántica distinta para esos valores NaN distintos).
Por ejemplo, un NaN de precisión simple IEEE 754 (32 bits) se codificaría como
s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
donde s es el signo (que suele ignorarse en las aplicaciones) y la secuencia x representa un número distinto de cero (el valor cero codifica infinitos). En la práctica, el bit más significativo de x se utiliza para determinar el tipo de NaN: "NaN silencioso" o "NaN de señalización" (consulte los detalles en Codificación). Los bits restantes codifican una carga útil (que suele ignorarse en las aplicaciones).
Las operaciones de punto flotante que no sean comparaciones ordenadas normalmente propagan un NaN silencioso ( qNaN ). La mayoría de las operaciones de punto flotante en un NaN de señalización ( sNaN ) señalan la excepción de operación no válida ; la acción de excepción predeterminada es entonces la misma que para los operandos qNaN y producen un qNaN si producen un resultado de punto flotante.
La propagación de NaN silenciosos a través de operaciones aritméticas permite detectar errores al final de una secuencia de operaciones sin realizar pruebas exhaustivas durante las etapas intermedias. Por ejemplo, si uno comienza con un NaN y suma 1 cinco veces seguidas, cada suma da como resultado un NaN, pero no hay necesidad de verificar cada cálculo porque uno puede simplemente notar que el resultado final es NaN. Sin embargo, dependiendo del lenguaje y la función, los NaN pueden eliminarse silenciosamente de una cadena de cálculos donde un cálculo en la cadena daría un resultado constante para todos los demás valores de punto flotante. Por ejemplo, el cálculo x 0 puede producir el resultado 1, incluso donde x es NaN, por lo que verificar solo el resultado final ocultaría el hecho de que un cálculo anterior a x 0 dio como resultado un NaN. En general, entonces, se necesita una prueba posterior para un indicador de inválido establecido para detectar todos los casos donde se introducen NaN [3] (ver la definición de la función a continuación para más detalles).
En la sección 6.2 del antiguo estándar IEEE 754-2008 , hay dos funciones anómalas (las funciones maxNum
y minNum
, que devuelven el máximo y el mínimo, respectivamente, de dos operandos que se espera que sean números) que favorecen a los números: si solo uno de los operandos es un NaN, se devuelve el valor del otro operando. La revisión IEEE 754-2019 ha reemplazado estas funciones, ya que no son asociativas (cuando aparece un NaN de señalización en un operando). [4] [5]
Las comparaciones están especificadas por el estándar IEEE 754 para tener en cuenta los posibles operandos NaN. [6] Al comparar dos números reales, o números reales extendidos (como en los formatos de punto flotante IEEE 754), el primer número puede ser menor, igual o mayor que el segundo número. Esto da tres relaciones posibles. Pero cuando al menos un operando de una comparación es NaN, esta tricotomía no se aplica y se necesita una cuarta relación: unordered . En particular, dos valores NaN se comparan como desordenados, no como iguales.
Como se especifica, los predicados asociados con los símbolos matemáticos <, ≤, =, ≥, > (o notación equivalente en lenguajes de programación) devuelven falso en una relación desordenada. Por lo tanto, por ejemplo, NOT ( x < y ) no es lógicamente equivalente a x ≥ y : en una relación desordenada, es decir, cuando x o y es NaN, el primero devuelve verdadero mientras que el segundo devuelve falso. Sin embargo, ≠ se define como la negación de =, por lo tanto devuelve verdadero en una relación desordenada.
A partir de estas reglas, comparando x consigo mismo, x ≠ x o x = x , se puede utilizar para comprobar si x es NaN o no NaN.
Los predicados de comparación son de señalización o no señalización en operandos NaN silenciosos; las versiones de señalización señalan la excepción de operación no válida para tales comparaciones (es decir, de manera predeterminada, esto simplemente establece el indicador de estado correspondiente además del comportamiento de las versiones sin señalización). Los predicados de igualdad y desigualdad son de no señalización. Los otros predicados de comparación estándar asociados con los símbolos matemáticos anteriores son todos de señalización si reciben un operando NaN. El estándar también proporciona versiones sin señalización de estos otros predicados. El predicado determina si un valor es un NaN y nunca señala una excepción, incluso si x es un NaN de señalización.isNaN(x)
El estándar de punto flotante IEEE exige que se cumpla NaN ≠ NaN . En cambio, el estándar privado de aritmética posit de 2022 tiene un concepto similar, NaR (Not a Real), donde NaR = NaR es válido. [7]
Hay tres tipos de operaciones que pueden devolver NaN: [8]
pow
función estándar y la pown
función de exponente entero definen 0 0 , 1 ∞ y ∞ 0 como 1 .powr
función define las tres formas indeterminadas como operaciones no válidas y, por lo tanto, devuelve NaN.Los NaN también pueden asignarse explícitamente a las variables, normalmente como representación de valores faltantes. Antes del estándar IEEE, los programadores solían utilizar un valor especial (como −99999999) para representar valores indefinidos o faltantes, pero no había garantía de que se manejaran de forma coherente o correcta. [1]
No necesariamente se generan NaN en todos los casos anteriores. Si una operación puede producir una condición de excepción y las trampas no están enmascaradas, entonces la operación causará una trampa en su lugar. [9] Si un operando es un NaN silencioso y tampoco hay ningún operando NaN de señalización, entonces no hay condición de excepción y el resultado es un NaN silencioso. Las asignaciones explícitas no causarán una excepción ni siquiera para los NaN de señalización.
En general, los NaN silenciosos, o qNaN, no generan excepciones adicionales, ya que se propagan a través de la mayoría de las operaciones. Sin embargo, la excepción de operación no válida se indica mediante algunas operaciones que no devuelven un valor de punto flotante, como las conversiones de formato o ciertas operaciones de comparación.
Los NaN de señalización, o sNaN, son formas especiales de un NaN que, cuando son consumidos por la mayoría de las operaciones, deberían generar la excepción de operación no válida y luego, si corresponde, "silenciarse" en un qNaN que luego puede propagarse. Se introdujeron en IEEE 754. Ha habido varias ideas sobre cómo se podrían utilizar:
Cuando se encuentra, un manejador de trampas podría decodificar el sNaN y devolver un índice al resultado calculado. En la práctica, este enfoque se enfrenta a muchas complicaciones. El tratamiento del bit de signo de los NaN para algunas operaciones simples (como el valor absoluto ) es diferente al de las operaciones aritméticas. Las trampas no son requeridas por el estándar. [ cita requerida ]
IEEE 754-2019 recomienda que se implementen las operaciones getPayload , setPayload y setPayloadSignaling [10] , estandarizando el acceso a las cargas útiles para agilizar el uso de las aplicaciones. [11] Según el documento de referencia IEEE 754-2019, esta recomendación debe interpretarse como "requerida para nuevas implementaciones, con reserva de compatibilidad con versiones anteriores". [12]
En los formatos de intercambio IEEE 754 , los NaN se identifican mediante patrones de bits específicos y predefinidos exclusivos de los NaN. El bit de signo no importa. Los NaN en formato binario se representan con el campo exponencial lleno de unos (como los valores infinitos) y algún número distinto de cero en el campo de significación (para diferenciarlos de los valores infinitos). El estándar IEEE 754 original de 1985 ( IEEE 754-1985 ) solo describía formatos binarios de punto flotante y no especificaba cómo se debía etiquetar el estado de señalización/silencio. En la práctica, el bit más significativo del campo de significación determinaba si un NaN estaba en señalización o en silencio. Se obtuvieron dos implementaciones diferentes, con significados invertidos:
is_quiet
is_signaling
bandera.Se ha preferido la primera opción, ya que permite que la implementación silencie un NaN de señalización simplemente configurando el bit de señalización/silencio en 1. Lo inverso no es posible con la última opción, ya que configurar el bit de señalización/silencio en 0 podría generar un infinito. [13]
Las revisiones de 2008 y 2019 del estándar IEEE 754 establecen requisitos y recomendaciones formales para la codificación del estado de señalización/silencio.
is_quiet
indicador. [15] Es decir, este bit no es cero si el NaN es silencioso y cero si el NaN es de señalización.is_signaling
indicador. Es decir, este bit es cero si el NaN está en silencio y no es cero si el NaN está enviando señales. [16]Para cumplir con la norma IEEE 754-2008, el significado del bit de señalización/silencio en los procesadores MIPS recientes ahora se puede configurar a través del campo NAN2008 del registro FCSR. Esta compatibilidad es opcional en la versión 3 de MIPS y obligatoria en la versión 5. [17]
El estado/valor de los bits restantes del campo de mantisa no está definido por el estándar. Este valor se denomina "carga útil" del NaN. Si una operación tiene una única entrada NaN y la propaga a la salida, la carga útil del NaN resultante debe ser la del NaN de entrada (esto no siempre es posible para formatos binarios cuando el estado de señalización/silencio está codificado por un is_signaling
indicador, como se explicó anteriormente). Si hay múltiples entradas NaN, la carga útil del NaN resultante debe ser de uno de los NaN de entrada; el estándar no especifica cuál.
Varios sistemas tienen el concepto de "NaN canónico", donde se elige un valor NaN específico para que sea el único qNaN posible generado por operaciones de punto flotante que no tengan una entrada NaN. El valor suele elegirse para que sea un NaN silencioso con una carga útil de todos ceros y un bit de signo definido arbitrariamente.
El uso de una cantidad limitada de representaciones NaN permite que el sistema use otros valores NaN posibles para fines no aritméticos, siendo el más importante el "NaN-boxing", es decir, usar la carga útil para datos arbitrarios. [23] (Este concepto de "NaN canónico" no es el mismo que el concepto de "codificación canónica" en IEEE 754).
Existen diferencias de opinión sobre la definición adecuada del resultado de una función numérica que recibe un NaN silencioso como entrada. Una opinión es que el NaN debería propagarse a la salida de la función en todos los casos para propagar la indicación de un error. Otra opinión, y la adoptada por las normas ISO C99 e IEEE 754-2008 en general, es que si la función tiene múltiples argumentos y la salida está determinada de forma única por todas las entradas que no son NaN (incluido el infinito), entonces ese valor debería ser el resultado. Así, por ejemplo, el valor devuelto por hypot(±∞, qNaN)
y hypot(qNaN, ±∞)
es +∞.
El problema es particularmente agudo para la función exponencial = x y . Las expresiones 0 0 , ∞ 0 y 1 ∞ se consideran formas indeterminadas cuando aparecen como límites (al igual que ∞ × 0), y la cuestión de si cero elevado a cero debe definirse como 1 ha dividido la opinión.pow(x, y)
Si la salida se considera indefinida cuando un parámetro no está definido, entonces pow(1, qNaN)
debería producir un qNaN. Sin embargo, las bibliotecas matemáticas normalmente han devuelto 1 para cualquier número real y , e incluso cuando y es un infinito . De manera similar, producen 1 para incluso cuando x es 0 o un infinito. La razón para devolver el valor 1 para las formas indeterminadas fue que el valor de las funciones en puntos singulares se puede tomar como un valor particular si ese valor está en el límite el valor [ aclaración necesaria ] para todos excepto una parte minúscula de una bola alrededor del valor límite de los parámetros. [ cita necesaria ] La versión 2008 del estándar IEEE 754 dice que y deberían devolver 1 ya que devuelven 1 independientemente de lo que se use en lugar de quiet NaN. Además, ISO C99, y más tarde IEEE 754-2008, eligieron especificar = 1 en lugar de qNaN; La razón de esta elección se da en la justificación de C: [24] "Generalmente, C99 evita un resultado NaN cuando es útil un valor numérico. ... El resultado de es +∞, porque todos los valores de punto flotante positivos grandes son números enteros pares".pow(1, y)
pow(x, 0)
pow(1, qNaN)
pow(qNaN, 0)
pow(−1, ±∞)
pow(−2, ∞)
Para satisfacer a aquellos que desean una interpretación más estricta de cómo debe actuar la función potencia, el estándar de 2008 define dos funciones potencia adicionales: , donde el exponente debe ser un entero, y , que devuelve un NaN siempre que un parámetro sea un NaN o la exponenciación daría una forma indeterminada .pown(x, n)
powr(x, y)
La mayoría de los formatos de enteros de tamaño fijo no pueden indicar explícitamente datos no válidos. En tal caso, al convertir NaN a un tipo entero, el estándar IEEE 754 requiere que se señale la excepción de operación no válida. Por ejemplo, en Java , tales operaciones lanzan instancias de java.lang.ArithmeticException
. [25] En C , conducen a un comportamiento indefinido , pero si se admite el anexo F, la operación produce una excepción de punto flotante "no válida" (como lo requiere el estándar IEEE) y un valor no especificado.
El paquete de PerlMath::BigInt
utiliza "NaN" para el resultado de cadenas que no representan números enteros válidos. [26]
> perl -mMath::BigInt -e "imprimir Math::BigInt->new('foo')" NaN
Diferentes sistemas operativos y lenguajes de programación pueden tener diferentes representaciones de cadenas de NaN.
nan (C, C++, Python)NaN (ECMAScript, Rust, C#, Julia). Julia puede mostrar NaN alternativo, según la precisión, NaN32 y NaN16; NaN es para el tipo Float64.Yaya%Lenguaje de programación no nativo (C, C++, Rust)NaNQ (IBM XL y AIX: propuesta Fortran, C++ n2290)NaNS (ídem)qNaNsNaN1.#SNAN (Excel)1.#CuentacuentasNúmero (Excel)-1.#IND (Excel)+nan.0 (Esquema)
Dado que, en la práctica, los NaN codificados tienen un signo, un bit de silencio/señalización e "información de diagnóstico" opcional (a veces denominada carga útil ), estos también se encontrarán ocasionalmente en representaciones de cadenas de NaN. Algunos ejemplos son:
-nan
) cuando están presentes. No existe una visualización estándar de la carga útil ni del estado de señalización, pero se puede construir un valor NaN silencioso de una carga útil específica proporcionando la cadena a una función de análisis de números (por ejemplo, ) o proporcionando la cadena de secuencia de caracteres a (o para sNaN), ambas interpretadas de una manera definida por la implementación.nan(char-sequence)
strtod
nan()
nans()
nan()
y nans()
. Analizan la secuencia de caracteres como un entero para strtoull
(o un equivalente de tamaño diferente) con su detección de bases enteras.nan()
análisis, pero strtod()
acepta un formato hexadecimal sin prefijo.No todos los lenguajes admiten la existencia de varios NaN. Por ejemplo, ECMAScript solo utiliza un valor NaN en todo el texto.
En su mayor parte, la plataforma Java SE trata los valores NaN de un tipo determinado como si estuvieran fusionados en un único valor canónico y, por lo tanto, esta especificación normalmente se refiere a un NaN arbitrario como si fuera un valor canónico.
Si se proporcionan
caracteres…
, se utilizan de una forma no especificada para seleccionar una representación particular de NaN (puede haber varias).