Stavo scrivendo un esempio istruttivo per un collega per mostrargli perché testare i galleggianti per l'uguaglianza è spesso una cattiva idea. L'esempio che ho seguito è stato aggiungere .1 dieci volte e confrontandolo con 1.0 (quello che ho mostrato nella mia classe numerica introduttiva). Sono stato sorpreso di scoprire che i due risultati erano uguali a (code + output).CLR Le ottimizzazioni JIT violano la causalità?
float @float = 0.0f;
for(int @int = 0; @int < 10; @int += 1)
{
@float += 0.1f;
}
Console.WriteLine(@float == 1.0f);
Alcune indagini hanno dimostrato che questo risultato non può essere invocato (come l'uguaglianza del float). Quello che ho trovato più sorprendente è che aggiungendo il codice dopo l'altro codice potrebbe cambiare il risultato del calcolo (code + output). Si noti che questo esempio ha esattamente lo stesso codice e IL, con un'ultima riga di C# aggiunta.
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"));
So che non dovrei usare l'uguaglianza su carri e, quindi, non dovrebbe preoccuparsi troppo di questo, ma ho trovato ad essere abbastanza sorprendente, come hanno fatto quasi tutti ho dimostrato che questo. Fare roba dopo il hai eseguito un calcolo cambia il valore del calcolo precedente? Non penso che questo sia il modello di calcolo che le persone hanno di solito nelle loro menti.
Non sono completamente perplesso, sembra sicuro assumere che ci sia un qualche tipo di ottimizzazione che si verifica nel caso "uguale" che modifica il risultato del calcolo (la costruzione in modalità debug impedisce il caso "uguale"). Apparentemente, l'ottimizzazione viene abbandonata quando il CLR scopre che in seguito dovrà boxare il float.
Ho cercato un po 'ma non ho trovato un motivo per questo comportamento. Qualcuno può identificarmi?
Buona risposta. Non lo chiamerei neanche un bug. Più di un effetto collaterale insolito (e sicuramente inaspettato). – Gobiner