mia risposta in altro thread non è del tutto corretto:.
realtà, quando calcolata in fase di esecuzione,
(byte)(64/0.8f)
è 80.
Quando lancia un float
contenente il risultato 64/0.8f
, a byte
in fase di esecuzione, il risultato effettivamente è 80. Tuttavia, questo non è il caso quando il cast è fatto come una parte del compito:
float f1 = (64/0.8f);
byte b1 = (byte) f1;
byte b2 = (byte)(64/0.8f);
Console.WriteLine(b1); //80
Console.WriteLine(b2); //79
Mentre b1 contiene il risultato previsto, b2 è disattivato. Secondo lo smontaggio, b2 è assegnato come segue:
mov dword ptr [ebp-48h],4Fh
Pertanto, il compilatore sembra calcolare un risultato diverso dal risultato in fase di esecuzione. Non so, tuttavia, se questo è il comportamento previsto o meno.
EDIT: Forse è l'effetto Pascal Cuoq descritto: Durante il tempo di compilazione, il compilatore C# utilizza double
per calcolare l'espressione. Ciò risulta in 79, xxx che viene troncato a 79 (come un doppio contiene abbastanza precisione da causare un problema, qui).
Usando float, tuttavia, non ci imbattiamo in alcun problema, poiché l'errore "virgola mobile" non si trova nell'intervallo di un float.
Durante il runtime, questa stampa anche 79:
double d1 = (64/0.8f);
byte b3 = (byte) d1;
Console.WriteLine(b3); //79
EDIT2: Come di richiesta di Pascal Cuoq, ho eseguito il seguente codice:
int sixtyfour = Int32.Parse("64");
byte b4 = (byte)(sixtyfour/0.8f);
Console.WriteLine(b4); //79
risultato è 79. Così il sopra affermazione che il compilatore e il runtime calcolano un risultato diverso non è vero.
Edit3: Quando si modifica il codice precedente (crediti a Pascal Cuoq, ancora), il risultato è 80:
byte b5 = (byte)(float)(sixtyfour/0.8f);
Console.WriteLine(b5); //80
Si noti, tuttavia, che questo non è il caso quando si scrive (risultati in 79):
byte b6 = (byte)(float)(64/0.8f);
Console.WriteLine(b6); //79
ecco cosa sembra accadere: (byte)(64/0.8f)
non viene valutato come un float
, ma valutati come double
(prima del getto a byte
). Ciò provoca un errore di arrotondamento (che non si verifica quando il calcolo viene eseguito utilizzando float
). Un cast esplicito da flottare prima di trasmettere a doppio (che è contrassegnato come ridondante da ReSharper, BTW) "risolve" questo problema. Tuttavia, quando il calcolo viene eseguito durante la compilazione (possibile quando si utilizzano solo le costanti), il cast esplicito a float
sembra essere ignorato/ottimizzato.
TLDR: i calcoli in virgola mobile sono ancora più complicati di quanto sembrino inizialmente.
Upvote per fare ulteriori ricerche - grande scoperta! – Matthias