Como funciona um NaN?

143 views
Skip to first unread message

Rodrigo Strauss

unread,
Jan 1, 2009, 7:18:50 PM1/1/09
to ccppb...@googlegroups.com
Eu sei que existe Wikipedia, mas me parece uma boa pergunta de ano
novo. Eu sei que é primeiro de janeiro, mas todo dia é dia de escovar
bits. Ah, feliz ano novo a todos.

Estou analizando o Protocol Buffer do Google
(http://code.google.com/p/protobuf/) e vi um código aparentemente
bizarro:

<code>
//
// ver http://www.google.com/codesearch/p?hl=en#WTeibokF6gE/trunk/src/google/protobuf/stubs/strutil.cc&q=strutil.cc&l=57
//
inline bool IsNaN(double value) {
// NaN is never equal to anything, even itself.
return value != value;
}
</code>

Isso me parece bem paradoxal. Qual a explicação para isso?

Rodrigo Strauss
http://www.1bit.com.br
PS: como não temos o lameless filter do Slashdot, aqui vai: 2009 first post!!!

Jorge Pereira

unread,
Jan 1, 2009, 7:35:17 PM1/1/09
to ccppb...@googlegroups.com
Rodrigo,

  Não me recordo bem o nome, mais e algo relacionado a precisão dos valores flutuantes.

ex:

  double a = 2.2, b = 2.2;

e no caso podendo ser

2.20000003
2.20000006

PS: Esqueci o link, pois tivemos problemas relacionados ao assunto em um projeto passado que participei, e utilizamos verificações do tipo!
bizarro né? também acho!

[]s
--
Regards,
+--------------------------------------------+
Jorge Pereira,
http://blog.jorgepereira.com.br/
+--------------------------------------------+

Rodrigo Kumpera

unread,
Jan 1, 2009, 9:47:38 PM1/1/09
to ccppb...@googlegroups.com
NaN significa "Not a Number" e, como o nome sugere, serve para representar
o conjunto de valores que não possuem representação numérica com FP.

Números imaginários são um exemplo, sqrt (-1) retorna NaN. Outro é dividir
zero ou +/- infinito por zero[1].

Um NaN por definição não é igual a nenhum outro número, inclusive a si próprio.
Isso se deve a sua característica monádica, na qual qualquer operação com um argumento
NaN resulta em NaN. Seu comportamento é análogo a mônada Maybe do Haskell.

Entender como NaN funciona é fundamental para produzir algoritmos numéricos corretos com FP.


[1] Dividir outros números por zero resulta em +/- inifinito com ieee 754.

Virgilio Alexandre Fornazin

unread,
Jan 2, 2009, 5:59:54 AM1/2/09
to ccppb...@googlegroups.com

Um texto legal sobre ponto flutuante:

"

Special Values

IEEE reserves exponent field values of all 0s and all 1s to denote special values in the floating-point scheme.

Zero

As mentioned above, zero is not directly representable in the straight format, due to the assumption of a leading 1 (we'd need to specify a true zero mantissa to yield a value of zero). Zero is a special value denoted with an exponent field of zero and a fraction field of zero. Note that -0 and +0 are distinct values, though they both compare as equal.

Denormalized

If the exponent is all 0s, but the fraction is non-zero (else it would be interpreted as zero), then the value is a denormalized number, which does not have an assumed leading 1 before the binary point. Thus, this represents a number (-1)s × 0.f × 2-126, where s is the sign bit and f is the fraction. For double precision, denormalized numbers are of the form (-1)s × 0.f × 2-1022. From this you can interpret zero as a special type of denormalized number.

Infinity

The values +infinity and -infinity are denoted with an exponent of all 1s and a fraction of all 0s. The sign bit distinguishes between negative infinity and positive infinity. Being able to denote infinity as a specific value is useful because it allows operations to continue past overflow situations. Operations with infinite values are well defined in IEEE floating point.

Not A Number

The value NaN (Not a Number) is used to represent a value that does not represent a real number. NaN's are represented by a bit pattern with an exponent of all 1s and a non-zero fraction. There are two categories of NaN: QNaN (Quiet NaN) and SNaN (Signalling NaN).

A QNaN is a NaN with the most significant fraction bit set. QNaN's propagate freely through most arithmetic operations. These values pop out of an operation when the result is not mathematically defined.

An SNaN is a NaN with the most significant fraction bit clear. It is used to signal an exception when used in operations. SNaN's can be handy to assign to uninitialized variables to trap premature usage.

Semantically, QNaN's denote indeterminate operations, while SNaN's denote invalid operations.

"

 

(http://steve.hollasch.net/cgindex/coding/ieeefloat.html)

 

 

 

 

   

 

 

 

 FORNAZIN CONSULTORIA Logo - Text.wmf

Virgilio Alexandre Fornazin

High performance and realtime systems development

 

Rua Brigadeiro Vicente Faria Lima, 268

Bela Vista    Leme-SP    CEP 13611-485

Phone: +55 19 3571-5573

Cell: +55 19 8111-4053

+55 11 8357 1491

Mail: virg...@fornazinconsultoria.com.br

Web: http://www.fornazinconsultoria.com.br

Fernando Gomes

unread,
Jan 2, 2009, 8:28:37 AM1/2/09
to ccppb...@googlegroups.com
Jorge,

    O NaN nada tem a ver com esta questão da precisão; aliás grande problema na questão de FP.
    Mas minha experiência com FP é das piores, quase traumática, portanto prefiro evitar utilizar visto que as vezes ele parecer ser indomável! :-(
    
[ ]s

Fer.G0

2009/1/1 Jorge Pereira <jper...@gmail.com>

Jorge Pereira

unread,
Jan 2, 2009, 8:54:57 AM1/2/09
to ccppb...@googlegroups.com
Realmente,

Confundi legal! :)

--
Regards,
+--------------------------------------------+
Jorge Pereira,
http://blog.jorgepereira.com.br/
+--------------------------------------------+


2009/1/2 Fernando Gomes <fer...@googlemail.com>

Psycho Mantys

unread,
Jan 3, 2009, 9:18:17 PM1/3/09
to ccppb...@googlegroups.com


2009/1/1 Rodrigo Strauss <rod...@1bit.com.br>
##############################################################################

A explicação do kumpera é bem "esclarecedora".

Mas acho meio estranho esse codigo, parece rapido mas não deveria ser assim. Se existir um outro caso que o numero não seja iqual a ele mesmo, vai dar erro.

Eu usava assim para detectar os meus NaN:
isnormal
(x) or fpclassify(x) == FP_ZERO

mas descobri que existe:
std::isnan(x)

na <cmath>.

Mas acho que NaN não deveriam ocorrer em codigos quem estão funcionando certo :p.

Mas claro, sempre existe alguma cituação estranha :D.

--
Adote um pinguim, saiba como! Me mande um e-mail demonstrando interesse!

http://www.slackware.com
U.L. : 450347
Fnord

Rodrigo Kumpera

unread,
Jan 4, 2009, 12:37:10 PM1/4/09
to ccppb...@googlegroups.com


2009/1/4 Psycho Mantys <psycho...@gmail.com>



2009/1/1 Rodrigo Strauss <rod...@1bit.com.br>


Eu sei que existe Wikipedia, mas me parece uma boa pergunta de ano
novo. Eu sei que é primeiro de janeiro, mas todo dia é dia de escovar
bits. Ah, feliz ano novo a todos.

Estou analizando o Protocol Buffer do Google
(http://code.google.com/p/protobuf/) e vi um código aparentemente
bizarro:

<code>
//
// ver http://www.google.com/codesearch/p?hl=en#WTeibokF6gE/trunk/src/google/protobuf/stubs/strutil.cc&q=strutil.cc&l=57
//
inline bool IsNaN(double value) {
 // NaN is never equal to anything, even itself.
 return value != value;
}
</code>

Isso me parece bem paradoxal. Qual a explicação para isso?

Rodrigo Strauss
http://www.1bit.com.br
PS: como não temos o lameless filter do Slashdot, aqui vai: 2009 first post!!!


##############################################################################

A explicação do kumpera é bem "esclarecedora".

Mas acho meio estranho esse codigo, parece rapido mas não deveria ser assim. Se existir um outro caso que o numero não seja iqual a ele mesmo, vai dar erro.

Se existirem outros casos você está usando uma FPU que não implementa IEEE 754/854 ou tem bugs e, sinceramente, esse vai ser o menor dos seus problemas.

Testar o número contra ele mesmo é obviamente um teste por NaN, nada de especial nisso. Porém, claro, o argumento pela legibilidade fala mais alto e ter uma função/macro isnan é muito melhor.


Mas acho que NaN não deveriam ocorrer em codigos quem estão funcionando certo :p.

Mas claro, sempre existe alguma cituação estranha :D.


NaN ocorre naturalmente em código com FP. É uma boa forma de sinalizar problemas de estabilidade numérica ou convergência.
Sem falar que devido à natureza como NaN se propaga o torna uma ótima maneira de sinalizar erros, já que ele irá propagar
até o resultado final sem exigir qualquer forma de verificação de erros no corpo do algorítmo.



DQ

unread,
Jan 5, 2009, 6:57:24 AM1/5/09
to ccppbrasil
Assunto muito interessante!

Uma busca no Google (links abaixo) sugere que std::isnan ainda não é
implementado em alguns compiladores por não fazer parte da
especificação atual do C++ (mas vai fazer parte da próxima). O
"truque" de usar value!=value parece ser a forma padrão para o teste.

http://bytes.com/groups/c/588254-how-check-double-inf-nan
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.15

Sobre usar ou não o ponto flutuante, acho que é uma questão de saber
usar a ferramenta correta para a aplicação em vista. O erro mais comum
é usar ponto flutuante para aplicações financeira$. Por outro lado, em
aplicações científicas e de engenharia o ponto flutuante pode ser o
mais apropriado, desde que se saiba como usá-lo (tenha a impressão que
existem tratados a respeito de como minimizar e tratar as
imprecisões), tanto que quem criou uma norma para representação de
ponto flutuante foi o IEEE (Instituto de ENGENHEIROS Elelétricos e
Eletrônicos).

Saudações de Ano Novo a todos!

Daniel Quadros
(Engenheiro Eletrônico...)

Rodrigo Kumpera

unread,
Jan 5, 2009, 7:05:59 AM1/5/09
to ccppb...@googlegroups.com


2009/1/5 DQ <d.qu...@yahoo.com>


Sobre usar ou não o ponto flutuante, acho que é uma questão de saber
usar a ferramenta correta para a aplicação em vista. O erro mais comum
é usar ponto flutuante para aplicações financeira$.

Não existe nenhuma razão para se evitar ponto flutuante em aplicações financeiras
desde que a representação direta de dinheiro não seja com FP.


 

P.

unread,
Jan 5, 2009, 7:49:23 AM1/5/09
to ccppbrasil
On 5 jan, 09:57, DQ <d.quad...@yahoo.com> wrote:

> Uma busca no Google (links abaixo) sugere que std::isnan ainda não é
> implementado em alguns compiladores por não fazer parte da
> especificação atual do C++ (mas vai fazer parte da próxima). O
> "truque" de usar value!=value parece ser a forma padrão para o teste.

isnan e amigos foram padronizados em C99; se você tiver um ambiente
C99 à disposição do seu compilador C++, pode incluir <math.h> e usar a
declaração no namespace global.

--
P.

abarcelos

unread,
Jan 5, 2009, 9:32:57 AM1/5/09
to ccppbrasil
Achei uma explicação razoavel por que um NaN não deve ser igual a
nada, nem a si mesmo
"NaN stands for Not a Number

0/100 -> x -> infinity
0/0 -> y -> infinity

mathematically can you say as x=y
you cannot say x=y it is a false

both values are not defined and you cannot say as both are equal "
de http://x86.sun.com/thread.jspa?messageID=9677939

Agora me pergunto como um NaN deve ser representado internamente...

Thiago Adams

unread,
Jan 5, 2009, 10:29:24 AM1/5/09
to ccppbrasil
> Achei uma explicação razoavel por que um NaN não deve ser igual a
> nada, nem a si mesmo
> "NaN stands for Not a Number

> 0/100 -> x -> infinity
> 0/0 -> y -> infinity

Não sei da onde veio esta parte, só queria deixar claro e não gerar má
interpretação matemática que:

0/100 = 0, porque 0 x 100 = 0; (ou seja não é infinito, muito menos
indeterminado)

e

0/0 é indeterminado, porque "qualquer coisa" vezes zero = zero. (ou
seja, indeterminado não é mesma coisa que infinito)


abarcelos

unread,
Jan 5, 2009, 12:37:24 PM1/5/09
to ccppbrasil
realmente, não sei de onde veio estes infinitos,
acredito que o ponto sejam as funções indeterminadas (http://
en.wikipedia.org/wiki/
Indeterminate_forms#List_of_indeterminate_forms),
se você tiver
a = 0/0
b = 0^0
'a' e 'b' seriam um NaN
se NaN fosse uma simples constante, 'a' == 'b' seria true...

Rodrigo Kumpera

unread,
Jan 5, 2009, 1:18:43 PM1/5/09
to ccppb...@googlegroups.com
Eles vem da forma como funciona matemática com ponto flutuante.

Um pouco de teoria e estudo devem sanar suas dúvidas.


2009/1/5 abarcelos <abar...@gmail.com>
Reply all
Reply to author
Forward
0 new messages