Otimizações CLR JIT violam causalidade?
Eu estava escrevendo um exemplo instrutivo para um colega para mostrar a ele por que testar carros alegóricos para igualdade geralmente é uma má idéia. O exemplo com o qual eu adicionei foi adicionando .1 dez vezes e comparando com 1,0 (o que foi mostrado na minha aula numérica introdutória). Fiquei surpreso ao descobrir que os dois resultadoseram iguais (código + saída)
float @float = 0.0f;
for(int @int = 0; @int < 10; @int += 1)
{
@float += 0.1f;
}
Console.WriteLine(@float == 1.0f);
Algumas investigações mostraram que esse resultado não podia ser invocado (como a igualdade de flutuação). O que eu achei mais surpreendente foi que adicionar códigodepois de o outro código pode alterar o resultado do cálculo (código + saída) Observe que este exemplo tem exatamente o mesmo código e IL, com mais uma linha de C # anexada.
float @float = 0.0f;
for(int @int = 0; @int < 10; @int += 1)
{
@float += 0.1f;
}
Console.WriteLine(@float == 1.0f);
Console.WriteLine(@float.ToString("G9"));
Eu sei que não devo usar a igualdade em carros alegóricos e, portanto, não deveria me importar muito com isso, mas achei bastante surpreendente, assim como todos que eu mostrei isso. Fazendo coisasdepois de você efetuou um cálculo altera o valor do cálculo anterior? Eu não acho que esse seja o modelo de computação que as pessoas geralmente têm em mente.
Não estou totalmente perplexo, parece seguro assumir que há algum tipo de otimização ocorrendo no caso "igual" que altera o resultado do cálculo (a criação no modo de depuração impede o caso "igual"). Aparentemente, a otimização é abandonada quando o CLR descobre que mais tarde precisará encaixar o float.
Pesquisei um pouco, mas não consegui encontrar uma razão para esse comportamento. Alguém pode me identificar?