Eu sei que você não pode confiar na igualdade entre valores de tipo duplo ou decimal normalmente, mas estou me perguntando se 0 é um caso especial.
Embora eu possa entender imprecisões entre 0,00000000000001 e 0,00000000000002, 0 em si parece muito difícil de errar, já que não é nada. Se você for impreciso sobre nada, não é mais nada.
Mas não sei muito sobre esse assunto, então não cabe a mim dizer.
double x = 0.0;
return (x == 0.0) ? true : false;
Isso sempre retornará verdadeiro?
Respostas:
É seguro esperar que a comparação retornará
true
se e somente se a variável double tiver um valor de exatamente0.0
(que em seu trecho de código original é, obviamente, o caso). Isso é consistente com a semântica do==
operador.a == b
significa "a
é igual ab
".Não é seguro (porque não é correto ) esperar que o resultado de algum cálculo seja zero em aritmética dupla (ou mais geralmente, ponto flutuante) sempre que o resultado do mesmo cálculo em matemática pura for zero. Isso ocorre porque quando os cálculos são feitos, o erro de precisão de ponto flutuante aparece - um conceito que não existe na aritmética de números reais na matemática.
fonte
Se você precisar fazer muitas comparações de "igualdade", pode ser uma boa ideia escrever uma pequena função auxiliar ou método de extensão no .NET 3.5 para comparar:
Isso pode ser usado da seguinte maneira:
fonte
Para sua amostra simples, esse teste está correto. Mas e quanto a isso:
Lembre-se de que .1 é um decimal repetido em binário e não pode ser representado exatamente. Em seguida, compare isso com este código:
Vou deixá-lo fazer um teste para ver os resultados reais: é mais provável que você se lembre dessa forma.
fonte
Na entrada MSDN para Double.Equals :
Além disso, consulte Double.Epsilon .
fonte
x.Equals(y)
, então(1/x).Equals(1/y)
, mas esse não é o caso sex
é0
ey
é1/Double.NegativeInfinity
. Esses valores são declarados iguais, embora seus recíprocos não.x = 0
ey = 0
, e ainda assim descobriria1/x != 1/y
.x
ey
como tipodouble
? Como você compara os resultados para torná-los relatados desiguais? Observe que 1 / 0,0 não é NaN.1.0/0.0
não é NaN como deveria ser, pois o limite não é único. Em segundo lugar, que os infinitos se comparam iguais entre si, sem prestar atenção aos graus do infinito)O problema surge quando você está comparando diferentes tipos de implementação de valor de ponto flutuante, por exemplo, comparando float com double. Mas com o mesmo tipo, não deve ser um problema.
O problema é que o programador às vezes esquece que a conversão de tipo implícito (double to float) está acontecendo para a comparação e isso resulta em um bug.
fonte
Se o número foi atribuído diretamente ao float ou double, então é seguro testar contra zero ou qualquer número inteiro que pode ser representado em 53 bits para um double ou 24 bits para um float.
Ou, colocando de outra forma, você sempre pode atribuir um valor inteiro a um duplo e, em seguida, comparar o duplo de volta ao mesmo inteiro e ter a garantia de que será igual.
Você também pode começar atribuindo um número inteiro e fazer comparações simples continuarem a funcionar, aderindo à adição, subtração ou multiplicação por números inteiros (assumindo que o resultado seja inferior a 24 bits para um float abd 53 bits para um duplo). Portanto, você pode tratar floats e doubles como inteiros sob certas condições controladas.
fonte
Não, não está bem. Os chamados valores desnormalizados (subnormais), quando comparados iguais a 0,0, seriam comparados como falsos (diferentes de zero), mas quando usados em uma equação seriam normalizados (se tornariam 0,0). Portanto, usar isso como um mecanismo para evitar uma divisão por zero não é seguro. Em vez disso, adicione 1.0 e compare com 1.0. Isso garantirá que todos os subnormais sejam tratados como zero.
fonte
Tente isso e você descobrirá que == não é confiável para double / float.
double d = 0.1 + 0.2; bool b = d == 0.3;
Aqui está a resposta do Quora.
fonte
Na verdade, acho melhor usar os seguintes códigos para comparar um valor duplo com 0,0:
O mesmo para flutuador:
fonte