Mam następujący prosty kod:
int speed1 = (int)(6.2f * 10);
float tmp = 6.2f * 10;
int speed2 = (int)tmp;
speed1
i speed2
powinien mieć tę samą wartość, ale w rzeczywistości mam:
speed1 = 61
speed2 = 62
Wiem, że powinienem prawdopodobnie użyć Math.Round zamiast rzutowania, ale chciałbym zrozumieć, dlaczego wartości są różne.
Spojrzałem na wygenerowany kod bajtowy, ale oprócz sklepu i obciążenia, kody operacyjne są takie same.
Próbowałem też tego samego kodu w javie i poprawnie otrzymałem 62 i 62.
Czy ktoś może to wyjaśnić?
Edycja: W prawdziwym kodzie nie jest to bezpośrednio 6,2f * 10, ale wywołanie funkcji * stała. Mam następujący kod bajtowy:
dla speed1
:
IL_01b3: ldloc.s V_8
IL_01b5: callvirt instance float32 myPackage.MyClass::getSpeed()
IL_01ba: ldc.r4 10.
IL_01bf: mul
IL_01c0: conv.i4
IL_01c1: stloc.s V_9
dla speed2
:
IL_01c3: ldloc.s V_8
IL_01c5: callvirt instance float32 myPackage.MyClass::getSpeed()
IL_01ca: ldc.r4 10.
IL_01cf: mul
IL_01d0: stloc.s V_10
IL_01d2: ldloc.s V_10
IL_01d4: conv.i4
IL_01d5: stloc.s V_11
widzimy, że operandy są zmiennoprzecinkowymi i jedyną różnicą jest stloc/ldloc
.
Jeśli chodzi o maszynę wirtualną, próbowałem z Mono / Win7, Mono / MacOS i .NET / Windows, z tymi samymi wynikami.