Pregunta
Tengo un programa que intenta reducir una double
abajo hasta el número deseado. La salida que se ve es NaN
.
¿Qué significa NaN
en Java?
Solución
"NaN" significa "no es un número". "Yaya" se produce si un punto flotante operación tiene algunos parámetros de entrada que causa la operación para producir un resultado no definido. Por ejemplo, 0.0 dividido por 0.0 no está definida aritméticamente. Tomando la raíz cuadrada de un número negativo también es indefinido.
Otros consejos
medios NaN
“no es un número” y es básicamente una representación de un valor de punto flotante especial en el IEE 754 flotante estándar punto . NaN generalmente significa que el valor es algo que no se puede expresar con un número de coma flotante válido.
Una conversión se traducirá en este valor, cuando el ser valor convertido es otra cosa, por ejemplo, cuando la conversión de una cadena que no representa un número.
medios NaN
"no es un número" y es el resultado de las operaciones definidas en los números de coma flotante como por ejemplo dividiendo cero por cero. (Tenga en cuenta que mientras que la división de un no-cero número por cero también se suele sin definir en matemáticas, que no da lugar a NaN pero en el infinito positivo o negativo).
medios NaN
"No es un número." Es un valor de punto flotante especial que significa que el resultado de una operación no se ha definido o no representable como un número real.
aquí para obtener una explicación más detallada de este valor.
NaN significa no un número. Se utiliza para significar cualquier valor que no está definido matemáticamente. Como dividir 0,0 por 0,0. Usted puede mirar aquí para obtener más información: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm
Publica tu programa aquí si necesita más ayuda.
NaN = Not a Number.
Medios no un número. Es una representación común para un valor numérico imposible en muchos lenguajes de programación.
No es un tipo de Java, pero en JS y otros idiomas lo uso de "Not a Number", lo que significa una operación provocó que se convierta en no es un número válido.
Es, literalmente, significa "no es un número." Me algo sospechoso está mal con su proceso de conversión.
Visita la sección no es un número en esta referencia
No es un valor de punto flotante válido (por ejemplo, el resultado de la división por cero)
Minimal ejemplo runnable
Lo primero que hay que saber, es que el concepto de NaN se lleva a cabo directamente en el hardware de la CPU.
Todos los principales CPU modernas parecen seguir IEEE 754 que especifica formatos de punto flotante, y NaNs , que son valores especiales solo flotador, son parte de esa norma.
Por lo tanto, el concepto será el muy similar en cualquier idioma, incluyendo Java, que simplemente emite código de punto flotante directamente a la CPU.
Antes de continuar, es posible que desee leer primero las siguientes respuestas que he escrito:
- un repaso rápido del formato de coma flotante IEEE 754: ¿Qué es un número de coma flotante debajo de lo normal?
- algunos conceptos básicos NaN nivel inferior cubiertos usando C / C ++: ¿Cuál es la diferencia entre la calma y la señalización NaN NaN?
Ahora un poco de acción de Java. La mayor parte de las funciones de interés que no están en el núcleo del lenguaje interior en vivo java.lang.Float
.
Nan.java
import java.lang.Float;
import java.lang.Math;
public class Nan {
public static void main(String[] args) {
// Generate some NaNs.
float nan = Float.NaN;
float zero_div_zero = 0.0f / 0.0f;
float sqrt_negative = (float)Math.sqrt(-1.0);
float log_negative = (float)Math.log(-1.0);
float inf_minus_inf = Float.POSITIVE_INFINITY - Float.POSITIVE_INFINITY;
float inf_times_zero = Float.POSITIVE_INFINITY * 0.0f;
float quiet_nan1 = Float.intBitsToFloat(0x7fc00001);
float quiet_nan2 = Float.intBitsToFloat(0x7fc00002);
float signaling_nan1 = Float.intBitsToFloat(0x7fa00001);
float signaling_nan2 = Float.intBitsToFloat(0x7fa00002);
float nan_minus = -nan;
// Generate some infinities.
float positive_inf = Float.POSITIVE_INFINITY;
float negative_inf = Float.NEGATIVE_INFINITY;
float one_div_zero = 1.0f / 0.0f;
float log_zero = (float)Math.log(0.0);
// Double check that they are actually NaNs.
assert Float.isNaN(nan);
assert Float.isNaN(zero_div_zero);
assert Float.isNaN(sqrt_negative);
assert Float.isNaN(inf_minus_inf);
assert Float.isNaN(inf_times_zero);
assert Float.isNaN(quiet_nan1);
assert Float.isNaN(quiet_nan2);
assert Float.isNaN(signaling_nan1);
assert Float.isNaN(signaling_nan2);
assert Float.isNaN(nan_minus);
assert Float.isNaN(log_negative);
// Double check that they are infinities.
assert Float.isInfinite(positive_inf);
assert Float.isInfinite(negative_inf);
assert !Float.isNaN(positive_inf);
assert !Float.isNaN(negative_inf);
assert one_div_zero == positive_inf;
assert log_zero == negative_inf;
// Double check infinities.
// See what they look like.
System.out.printf("nan 0x%08x %f\n", Float.floatToRawIntBits(nan ), nan );
System.out.printf("zero_div_zero 0x%08x %f\n", Float.floatToRawIntBits(zero_div_zero ), zero_div_zero );
System.out.printf("sqrt_negative 0x%08x %f\n", Float.floatToRawIntBits(sqrt_negative ), sqrt_negative );
System.out.printf("log_negative 0x%08x %f\n", Float.floatToRawIntBits(log_negative ), log_negative );
System.out.printf("inf_minus_inf 0x%08x %f\n", Float.floatToRawIntBits(inf_minus_inf ), inf_minus_inf );
System.out.printf("inf_times_zero 0x%08x %f\n", Float.floatToRawIntBits(inf_times_zero), inf_times_zero);
System.out.printf("quiet_nan1 0x%08x %f\n", Float.floatToRawIntBits(quiet_nan1 ), quiet_nan1 );
System.out.printf("quiet_nan2 0x%08x %f\n", Float.floatToRawIntBits(quiet_nan2 ), quiet_nan2 );
System.out.printf("signaling_nan1 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan1), signaling_nan1);
System.out.printf("signaling_nan2 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan2), signaling_nan2);
System.out.printf("nan_minus 0x%08x %f\n", Float.floatToRawIntBits(nan_minus ), nan_minus );
System.out.printf("positive_inf 0x%08x %f\n", Float.floatToRawIntBits(positive_inf ), positive_inf );
System.out.printf("negative_inf 0x%08x %f\n", Float.floatToRawIntBits(negative_inf ), negative_inf );
System.out.printf("one_div_zero 0x%08x %f\n", Float.floatToRawIntBits(one_div_zero ), one_div_zero );
System.out.printf("log_zero 0x%08x %f\n", Float.floatToRawIntBits(log_zero ), log_zero );
// NaN comparisons always fail.
// Therefore, all tests that we will do afterwards will be just isNaN.
assert !(1.0f < nan);
assert !(1.0f == nan);
assert !(1.0f > nan);
assert !(nan == nan);
// NaN propagate through most operations.
assert Float.isNaN(nan + 1.0f);
assert Float.isNaN(1.0f + nan);
assert Float.isNaN(nan + nan);
assert Float.isNaN(nan / 1.0f);
assert Float.isNaN(1.0f / nan);
assert Float.isNaN((float)Math.sqrt((double)nan));
}
}
Ejecutar con:
javac Nan.java && java -ea Nan
Salida:
nan 0x7fc00000 NaN
zero_div_zero 0x7fc00000 NaN
sqrt_negative 0xffc00000 NaN
log_negative 0xffc00000 NaN
inf_minus_inf 0x7fc00000 NaN
inf_times_zero 0x7fc00000 NaN
quiet_nan1 0x7fc00001 NaN
quiet_nan2 0x7fc00002 NaN
signaling_nan1 0x7fa00001 NaN
signaling_nan2 0x7fa00002 NaN
nan_minus 0xffc00000 NaN
positive_inf 0x7f800000 Infinity
negative_inf 0xff800000 -Infinity
one_div_zero 0x7f800000 Infinity
log_zero 0xff800000 -Infinity
Así que de esto aprendemos algunas cosas:
-
raro operaciones que no tienen ninguna consecuencia dar sensata NaN flotante:
-
0.0f / 0.0f
-
sqrt(-1.0f)
-
log(-1.0f)
generar una
NaN
.En C, en realidad es posible señales de petición a ser elevado en este tipo de operaciones con
feenableexcept
para detectarlos, pero no creo que se expone en Java: ¿por qué la división entera por cero 1 / 0 error dar, pero coma flotante 1 / 0.0 devuelve "Inf"? -
-
operaciones extrañas que están en el límite de más o en menos infinito sin embargo damos + - infinito en lugar de NaN
-
1.0f / 0.0f
-
log(0.0f)
0.0
casi cae en esta categoría, pero es probable que el problema es que tampoco podía ir a más o menos infinito, por lo que se dejó como NaN. -
-
si NaN es la entrada de una operación flotante, la salida también tiende a ser NaN
-
hay varios valores posibles para NaN
0x7fc00000
,0x7fc00001
,0x7fc00002
, aunque x86_64 parece generar solamente0x7fc00000
. -
NaN y el infinito tienen representación binaria similar.
La ruptura de defraudado a algunos de ellos:
nan = 0x7fc00000 = 0 11111111 10000000000000000000000 positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000 negative_inf = 0xff800000 = 1 11111111 00000000000000000000000 | | | | | mantissa | exponent | sign
A partir de este Confirmamos lo IEEE754 especifica:
- tanto Nan y tienen infinitos exponente == 255 (todos unos)
- infinitos Tienes mantisa == 0. Hay, por tanto, sólo dos infinitos posibles: + y -, diferenciados por el bit de signo
- NaN tiene mantisa! = 0. Por consiguiente, existen varias posibilidades, a excepción de mantisa == 0, que es el infinito
-
NaNs puede ser positivo o negativo (parte superior bit), aunque esto no tiene ningún efecto en las operaciones normales
Probado en Ubuntu 18.10 AMD64, OpenJDK 1.8.0_191.