A resposta rápida para o problema proposto neste post, para não deixar vocês curiosos, é que o tipo de x é qualquer um dos tipos de ponto-flutuante (float, double e long double). Vocês se lembram dos 3 problemas do ponto-flutuante que já falei por aqui? (este, este e este). Este é mais um deles…
Valores em ponto-flutuante podem cair em 4 categorias: normalizados, não-normalizados, infinitos e não-números. Os valores normalizados são os que normalmente lidamos (hehe… não resisti). Sobre os não-normalizados ainda não falei e vou deixá-los de lado por agora. Os valores infinitos acontecem, por exemplo, quando você tenta obter o recíproco de um valor muito pequeno (não zero). Mas, o nosso problema mesmo são os não-números.
A coerência da comparação != devolver true para dois valores não-números é óbvia… Se eles não são números, não podem ser iguais. Dois exemplos de não-números (sigla em inglês: NaN) são os resultados das chamadas para as funções da biblioteca padrão de C: sqrtf() e log(), com valores negativos em ambos os casos. Ou seja, a √-1 existe, mas não é um número real (É um NaN!). Assim como o logarítimo de, por exemplo, -1, também é um NaN…
Esse comportamento da comparação entre NaNs faz parte tanto da especificação IEEE-754 (e, por isso, aplica-se a qualquer linguagem) quanto da especificação de C e C++.
Faça um teste:
#include <stdio.h> #include <math.h> int main(void) { float x; x = sqrtf(-1.0f); /* sqrt() retorna NAN */ if (x != x) puts("diferentes!"); return 0; }
Como sempre, peço pra vocês tomarem muito cuidado quando usarem ponto-flutuante! Prefiram aritimética inteira: É mais performática, é exata e não apresenta tantos problemas…