Pergunta

Eu sei que você não pode contar com a igualdade entre valores de tipo double ou decimal normalmente, mas eu estou querendo saber se 0 é um caso especial.

Embora eu possa compreender imprecisões entre ,00000000000001 e ,00000000000002, 0 em si parece bastante difícil de confusão uma vez que é apenas nada. Se você é imprecisa em nada, não é nada de mais.

Mas eu não sei muito sobre este tópico por isso não é para mim dizer.

double x = 0.0;
return (x == 0.0) ? true : false;

Will que sempre retornam verdade?

Foi útil?

Solução

É segura que esperar que a comparação retornará true se e somente se a variável duplo possui um valor de exatamente 0.0 (que em seu trecho de código original é, naturalmente, o caso). Isto é consistente com a semântica do operador ==. meios a == b "a é igual a b".

É não é segura (porque é não é correto ) arithmetics esperar que o resultado de algum cálculo será zero em dobro (ou mais geralmente, flutuante ponto) sempre que o resultado do mesmo cálculo em matemática pura é zero. Isto porque, quando os cálculos vêm para o chão, aparece erro de precisão de ponto flutuante -. Um conceito que não existe na aritmética com números reais em Matemática

Outras dicas

Se você precisa fazer um monte de comparações "igualdade" que poderia ser uma boa idéia para escrever uma função auxiliar ou método de extensão pouco em .NET 3.5 para comparar:

public static bool AlmostEquals(this double double1, double double2, double precision)
{
    return (Math.Abs(double1 - double2) <= precision);
}

Isto poderia ser usado da seguinte maneira:

double d1 = 10.0 * .1;
bool equals = d1.AlmostEquals(0.0, 0.0000001);

Para o seu exemplo simples, que o teste está bem. Mas o que dizer isto:

bool b = ( 10.0 * .1 - 1.0 == 0.0 );

Lembre-se que 0,1 é uma dízima periódica em binário e não pode ser representado exatamente. Então comparar com este código:

double d1 = 10.0 * .1; // make sure the compiler hasn't optimized the .1 issue away
bool b = ( d1 - 1.0 == 0.0 );

Vou deixar que você execute um teste para ver os resultados reais:. Você é mais propensos a lembrar-lo dessa maneira

A partir da entrada MSDN para Double.Equals :

Precision em comparações

O método Equals deve ser usado com cautela, porque dois aparentemente os valores equivalentes pode ser devido desigual à precisão diferentes dos dois valores. Os seguintes exemplos de relatórios que o valor Duplo 0,3333 eo Duplo voltou dividindo 1 por 3 são desigual.

...

Em vez de comparar a igualdade, uma técnica recomendada envolve definição de uma margem aceitável de diferença entre dois valores (tal como 0,01% de um dos valores). Se o valor absoluto da diferença entre os dois valores é inferior ou igual à margem, a diferença é provável que seja devido a diferenças na precisão e, portanto, os valores são susceptíveis de ser igual. Os seguintes exemplo usa essa técnica para comparar .33333 e 1/3, os dois valores Double que o exemplo de código anterior encontrada para ser desigual.

Além disso, veja Double.Epsilon .

O problema surge quando você está comparando tipos diferentes de implementação valor de ponto flutuante por exemplo comparando flutuador com o dobro. Mas com mesmo tipo, ele não deve ser um problema.

float f = 0.1F;
bool b1 = (f == 0.1); //returns false
bool b2 = (f == 0.1F); //returns true

O problema é, programador às vezes se esquece que tipo implícito elenco (duplo para float) está acontecendo para a comparação e o que resulta em um erro.

Se o número foi diretamente atribuído ao float ou double, então é seguro para teste contra zero ou qualquer número inteiro que pode ser representado em 53 bits para um casal ou 24 bits para um float.

Ou, dito de outra forma, você pode sempre atribuir e valor inteiro para um casal e, em seguida, comparar a volta duas vezes para o mesmo número inteiro e ser garantido que vai ser igual.

Você também pode começar por atribuir um número inteiro e ter comparações simples continuar a trabalhar aderindo a adição, subtração ou multiplicação por números inteiros (assumindo que o resultado é menos de 24 bits para um float abd 53 bits para um quarto duplo) . Então você pode tratar flutua e duplas como inteiros sob determinadas condições controladas.

Não, não é OK. Os chamados valores desnormalizada (subnormais), quando comparado igual a 0,0, compararia como falsa (não-zero), mas quando usado em uma equação seria normalizada (tornar-se 0.0). Assim, usando isto como um mecanismo para evitar uma divisão por zero não é seguro. Em vez disso, adicionar 1,0 e comparar a 1,0. Isso irá garantir que todos os subnormais são tratados como zero.

Tente isso, e você vai achar que == não é confiável para o dobro / float.
double d = 0.1 + 0.2; bool b = d == 0.3;

Aqui está o resposta de Quora.

Na verdade, eu acho que é melhor usar os seguintes códigos para comparar um valor duplo contra a 0.0:

double x = 0.0;
return (Math.Abs(x) < double.Epsilon) ? true : false;

Mesmo para float:

float x = 0.0f;
return (Math.Abs(x) < float.Epsilon) ? true : false;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top