Pergunta

Este código funciona (C # 3)

double d;
if(d == (double)(int)d) ...;
  1. Existe uma maneira melhor de fazer isso?
  2. Por razões estranhas que eu quero evitar a dupla elenco tão; o que maneiras agradáveis ??existe outros do que isso? (Mesmo que eles não são tão bons)

Nota: Várias pessoas apontaram o ponto (importante) que == é muitas vezes reclassificação problemática ponto flutuante. Nestes casos espero valores no intervalo de 0 a algumas centenas e eles deveriam ser inteiros (não ints são erros) por isso, se esses pontos "não deve" ser um problema para mim.

Foi útil?

Solução

d == Math.Floor(d)

faz a mesma coisa em outras palavras.

Nota: Esperamos que você está ciente de que você tem que ter muito cuidado ao fazer esse tipo de coisa; flutuadores / duplos será muito fácil acumular erros minúsculos que fazem comparações exatas (como este) falhar por nenhuma razão óbvia.

Outras dicas

Se o seu duplo é o resultado de um outro cálculo, você provavelmente vai querer algo como:

d == Math.Floor(d + 0.00001);

Assim, se houve um ligeiro erro de arredondamento, ele ainda vai corresponder.

Isso funcionaria eu penso:

if (d % 1 == 0) {
  //...
}

Eu não posso responder a parte espec�ico C # da questão, mas devo salientar que você provavelmente está faltando um problema genérico com números de ponto flutuante.

Geralmente, integerness não é bem definida em carros alegóricos. Pela mesma razão que a igualdade não é bem definida em carros alegóricos. Cálculos de ponto flutuante normalmente incluem tanto erros de arredondamento e de representação.

Por exemplo, 1.1 + 0.6 != 1.7.

Sim, isso é apenas a maneira como números de ponto flutuante de trabalho.

Aqui, 1.1 + 0.6 - 1.7 == 2.2204460492503131e-16.

A rigor, a coisa mais próxima para comparação de igualdade que você pode fazer com flutuadores está comparando-os até uma precisão escolhido .

Se isto não é suficiente, você deve trabalhar com uma representação número decimal, com uma representação número de ponto flutuante com built-in margem de erro, ou com os cálculos simbólicos.

Se você está indo só para convertê-lo, a resposta de Mike F / Khoth é bom, mas não chega a responder à sua pergunta. Se você estiver indo para realmente teste, e é realmente importante, eu recomendo que você implementar algo que inclui uma margem de erro.

Por exemplo, se você está pensando em dinheiro e você quer teste para valores até mesmo dólar, você pode dizer (seguindo o padrão de Khoth):

if( Math.abs(d - Math.Floor(d + 0.001)) < 0.001)

Em outras palavras, tomar o valor absoluto da diferença do valor e da representação inteira e garantir que ele é pequeno.

Você não precisa extra (duplo) lá dentro. Isso funciona:

if (d == (int)d) {
 //...
}

Use Math.Truncate ()

Um teste simples, como 'x == floor (x)' é matematicamente assegurado ao trabalho corretamente, para qualquer número de precisão fixo FP.

Todas as codificações FP de precisão fixa legais representam números reais distintos, e assim, para cada inteiro x, há no máximo FP codificação de uma precisão fixa que partidas exatamente.

Portanto, para cada inteiro x que pode ser representada de tal maneira, temos x == floor (x), necessariamente, uma vez que floor (x) por volta definição o maior número FP y tal que y <= x e y representa um número inteiro; assim floor (x) deve retornar x.

Isso permitirá que você escolha o que precisão você está procurando, mais ou menos metade de um carrapato, a conta para flutuante deriva ponto. A comparação também é integrante que é bom.

static void Main(string[] args)
{
    const int precision = 10000;

    foreach (var d in new[] { 2, 2.9, 2.001, 1.999, 1.99999999, 2.00000001 })
    {
        if ((int) (d*precision + .5)%precision == 0)
        {
            Console.WriteLine("{0} is an int", d);
        }
    }
}

e a saída é

2 is an int
1.99999999 is an int
2.00000001 is an int

Algo como isto

double d = 4.0;
int i = 4;

bool equal = d.CompareTo(i) == 0; // true

Você pode usar esta

    bool IsInt(double x)
    {
        try
        {
            int y = Int16.Parse(x.ToString());
            return true;
        }
        catch 
        {
            return false;
        }
    }

Para lidar com a precisão do double ...

Math.Abs(d - Math.Floor(d)) <= double.Epsilon

Considere o seguinte caso em que um valor menos de double.Epsilon não comparar como zero.

// number of possible rounds
const int rounds = 1;

// precision causes rounding up to double.Epsilon
double d = double.Epsilon*.75;

// due to the rounding this comparison fails
Console.WriteLine(d == Math.Floor(d));

// this comparison succeeds by accounting for the rounding
Console.WriteLine(Math.Abs(d - Math.Floor(d)) <= rounds*double.Epsilon);

// The difference is double.Epsilon, 4.940656458412465E-324
Console.WriteLine(Math.Abs(d - Math.Floor(d)).ToString("E15"));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top