Tenho um programa que tenta reduzir a double
até um número desejado. A saída que recebo é NaN
.
O que NaN
significa em Java?
Tenho um programa que tenta reduzir a double
até um número desejado. A saída que recebo é NaN
.
O que NaN
significa em Java?
Respostas:
Retirado desta página :
"NaN" significa "não é um número". "Nan" é produzido se uma operação de ponto flutuante tiver alguns parâmetros de entrada que fazem com que a operação produza algum resultado indefinido. Por exemplo, 0,0 dividido por 0,0 é aritmeticamente indefinido. Tirar a raiz quadrada de um número negativo também é indefinido.
NaN
tem a interessante propriedade de ser o único "número" que não é igual a si mesmo quando comparado. Portanto, um comum (e em muitas línguas a única) de teste se um número x
é NaN
o seguinte:boolean isNaN(x){return x != x;}
i
e algumas linguagens como o python lidam muito bem com isso ... Pode não ser o caso em java
tu
NaN
significa “Não é um número” e é basicamente uma representação de um valor de ponto flutuante especial no padrão de ponto flutuante IEE 754 . NaN geralmente significa que o valor é algo que não pode ser expresso com um número de ponto flutuante válido.
Uma conversão resultará neste valor, quando o valor que está sendo convertido é outro, por exemplo, ao converter uma string que não representa um número.
parseFloat()
ou parseDouble
? Ou alguma outra coisa?
NaN
significa "Não é um número" e é o resultado de operações indefinidas em números de ponto flutuante como, por exemplo, dividir zero por zero. (Observe que, embora dividir um número diferente de zero por zero também seja geralmente indefinido em matemática, isso não resulta em NaN, mas em infinito positivo ou negativo).
NaN
significa "Não é um número". É um valor de ponto flutuante especial que significa que o resultado de uma operação não foi definido ou não pode ser representado como um número real.
Veja aqui mais explicações sobre este valor.
NaN significa Não é um número. É usado para significar qualquer valor que seja matematicamente indefinido. Como dividir 0,0 por 0,0. Você pode procurar aqui para obter mais informações: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm
Poste seu programa aqui se precisar de mais ajuda.
NaN = Não é um número.
Exemplo de execução mínima
A primeira coisa que você precisa saber é que o conceito de NaN é implementado diretamente no hardware da CPU.
Todas as principais CPUs modernas parecem seguir IEEE 754 que especifica formatos de ponto flutuante, e NaNs, que são apenas valores flutuantes especiais, fazem parte desse padrão.
Portanto, o conceito será muito semelhante em qualquer linguagem, incluindo Java, que apenas emite código de ponto flutuante diretamente para a CPU.
Antes de continuar, você pode querer ler primeiro as seguintes respostas que escrevi:
Agora, para alguma ação Java. A maioria das funções de interesse que não estão na linguagem central estão internamente 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));
}
}
Correr com:
javac Nan.java && java -ea Nan
Resultado:
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
Assim, aprendemos algumas coisas:
operações flutuantes estranhas que não têm nenhum resultado lógico fornecem NaN:
0.0f / 0.0f
sqrt(-1.0f)
log(-1.0f)
gerar a NaN
.
Em C, é realmente possível solicitar o aumento de sinais em tais operações feenableexcept
para detectá-los, mas não acho que seja exposto em Java: Por que a divisão inteira por zero 1/0 dá erro, mas ponto flutuante 1 / 0,0 retorna "Inf"?
operações estranhas que estão no limite de mais ou menos infinito, no entanto, dão + - infinito em vez de NaN
1.0f / 0.0f
log(0.0f)
0.0
quase cai nesta categoria, mas provavelmente o problema é que ele poderia ir para mais ou menos infinito, então foi deixado como NaN.
se NaN for a entrada de uma operação flutuante, a saída também tende a ser NaN
existem vários valores possíveis para NaN 0x7fc00000
, 0x7fc00001
, 0x7fc00002
, embora x86_64 parece gerar apenas 0x7fc00000
.
NaN e infinito têm representação binária semelhante.
Vamos analisar alguns deles:
nan = 0x7fc00000 = 0 11111111 10000000000000000000000
positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000
negative_inf = 0xff800000 = 1 11111111 00000000000000000000000
| | |
| | mantissa
| exponent
|
sign
A partir disso, confirmamos o que IEEE754 especifica:
Os NaNs podem ser positivos ou negativos (bit superior), embora isso não tenha efeito sobre as operações normais
Testado no Ubuntu 18.10 amd64, OpenJDK 1.8.0_191.
Não sou um cara Java, mas em JS e outras linguagens eu uso "Not a Number", o que significa que alguma operação fez com que ele se tornasse um número inválido.
Literalmente significa "Não é um número". Suspeito que algo está errado com seu processo de conversão.
Verifique a seção Não é um número nesta referência
Não é um valor de ponto flutuante válido (por exemplo, o resultado da divisão por zero)