Casting double.NaN para int será 0.
Console.WriteLine(unchecked((int)double.NaN)); // 0
No entanto, atribuir double.NaN a uma variável e, em seguida, converter para int será -2147483648.
double value = double.NaN;
Console.WriteLine (unchecked ((int) value)); // -2147483648
Console.WriteLine ((int) value); // -2147483648
Por que o resultado muda dependendo se é ou não atribuído a uma variável?
Especificação C #
6.2.1 Conversões numéricas explícitas
- Em um contexto verificado, a conversão procede da seguinte forma:
- Se o valor do operando for NaN ou infinito, uma System.OverflowException é lançada.
- Caso contrário, o operando de origem é arredondado para zero para o valor integral mais próximo. Se esse valor integral estiver dentro do intervalo do tipo de destino, esse valor é o resultado da conversão.
- Caso contrário, uma System.OverflowException é lançada.
- Em um contexto não verificado, a conversão sempre é bem-sucedida e prossegue da seguinte maneira.
- Se o valor do operando for NaN ou infinito, o resultado da conversão é um valor não especificado do tipo de destino.
- Caso contrário, o operando de origem é arredondado para zero para o valor integral mais próximo. Se esse valor integral estiver dentro do intervalo do tipo de destino, esse valor é o resultado da conversão.
- Caso contrário, o resultado da conversão é um valor não especificado do tipo de destino.
Envrionment
- Compilador: Visual Studio 2013
- Rimtime: .NET Framework 4.6.0
- SO: Windows 10 Versão 1607
- CPU: Intel Core i7 920
Janelas:
Console.WriteLine(Environment.OSVersion); // Microsoft Windows NT 6.2.9200.0
Console.WriteLine(Environment.Version); // 4.0.30319.42000
Respostas:
3 para resposta № 1Por padrão, um aplicativo de console é compilado como unchecked
. É por isso que seu último exemplo mostra o mesmo valor que os exemplos usando explicitamente unchecked
.
Para o restante de seus exemplos, a seção de especificações que você citou se aplica:
- Em um contexto não verificado, a conversão sempre é bem-sucedida e prossegue da seguinte maneira.
- Se o valor do operando for NaN ou infinito, o resultado da conversão será um valor não especificado do tipo de destino.
(enfatizando por mim).
Não especificado significa que você não pode confiar no resultado. Pode ser 0
ou -2147483648
ou qualquer outra coisa.
Eu gostaria de descobrir o que acontece sob o capô em seu caso especial, mas eu entendo -2147483648
para ambas as maneiras. Portanto, é difícil rastrear.
1 para resposta № 2
Depois de olhar em volta, acho que entendi o que está acontecendo aqui. Você não está escalando 0, você está escalando NaN. int
ou Int32
tem um alcance muito menor do que double
. Eu pensar essas regras deliciosamente nada claras estão trabalhando juntas para fazer a diferença:
- Se o valor do operando for NaN ou infinito,o resultado da conversão é um valor não especificado do tipo de destino. Caso contrário, o operando de origem é arredondado para zero para o valor integral mais próximo.
- Se esse valor integral estiver dentro do intervalo do tipo de destino, esse valor é o resultado da conversão.
O tipo de destino aqui é o menor int
, e o valor "-2147483648" que você está recebendo é o valor mínimo de um inteiro assinado de 32 bits. Isso sugere que a operação de conversão está convertendo o NaN em double.NegativeInfinity
para realizar uma operação com ele. O inteiro mais próximo de double.NegativeInfinity
é int.MinValue
, que é o valor que você está obtendo.
Dito isso, o fato de que esse valor é não especificado significa que o resultado obtido também pode dependermuitos fatores, até mesmo se você atribuiu ou não uma variável ou mesmo qual arquitetura de processador você possui. Você não deve usar a conversão NaN para fazer algo significativo, então NaN nunca é atribuído um valor definido real (principalmente porque seria, por definição, um número). Para a maioria dos propósitos, um resultado NaN deve ser tratado como um erro por esse motivo. O valor real é, no final, sem sentido.