SORU
18 Ocak 2012, ÇARŞAMBA


C int için bir yüzer döküm zaman garip bir davranış#

Aşağıdaki basit kodu vardır :

int speed1 = (int)(6.2f * 10);
float tmp = 6.2f * 10;
int speed2 = (int)tmp;

speed1 ve hız2 aynı değere sahip olmalıdır, ama aslında var :

speed1 = 61
speed2 = 62

Muhtemelen Matematik kullanmam gerektiğini biliyorum.Döküm yerine yuvarlak, ama değerleri farklıdır neden anlamak istiyorum.

Üretilen bayt kodu, ama bir mağaza ve bir yük dışında, işlem kodları aynıdır baktım.

Ben de java da aynı kod çalıştı, ve ben doğru 62 62 elde edilir.

Biri bunu açıklayabilir mi ?

Düzenleme : Gerçek kodda, doğrudan 6.2 f * 10 değil ama işlev çağrısı bir sabit*. Aşağıdaki bayt kodu var :

hızlı 1 için :

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

hız 2 için :

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

işlenen yüzer ve tek fark stloc/ldloc olduğunu görebilirsiniz

Sanal makine için/Windows 7, Mono/MacOS Mono ile çalıştı, ve .NET Windows, aynı sonuçları ile

CEVAP
18 Ocak 2012, ÇARŞAMBA


Öncelikle, sanırım bunu bilmen 6.2f * 10 değil tam olarak 62 nedeniyle kayan nokta yuvarlama (aslında değeri 61.99999809265137 zaman ifade edildiği gibi bir double) ve bu, sorunu sadece neden iki görünüşte aynı hesaplamalar sonucu yanlış değer.

Cevap (int)(6.2f * 10) durumunda double değer 61.99999809265137 alarak ve 61 veren bir tam sayı olarak kesiliyor.

float f = 6.2f * 10, Bu durumda çift değer 61.99999809265137 ve alıyoryuvarlama62 float, yakın. Sen o zaman bir tamsayı için float bunu kesecek ve sonuç olarak 62.

Egzersiz: aşağıdaki işlemleri sırası sonuçlarını Açıklar.

double d = 6.2f * 10;
int tmp2 = (int)d;
// evaluate tmp2

Güncelleme: not açıklamalarda, ifade 6.2f * 10 resmen float beri ikinci parametre bir örtülü dönüşüm için float better daha örtülü dönüşüm için double.

Asıl sorun, derleyici izin (ama gerekli değil) higher precision than the formal type bir ara kullanmaktır. Bu yüzden farklı davranış, farklı sistemleri: ifade (int)(6.2f * 10) derleyici seçeneği vardır tutmak değer 6.2f * 10 yüksek hassasiyetli ara form dönüşmeden önce int. Eğer bunu yaparsa, o zaman sonuç 61. Eğer öyle değilse, o zaman sonuç 62.

İkinci örnekte float açık atama yuvarlama tamsayıya dönüştürme önce yer almaya zorlar.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • pilslajt

    pilslajt

    20 HAZİRAN 2008
  • Tek Syndicate

    Tek Syndicat

    23 Temmuz 2008
  • Vsauce

    Vsauce

    30 Temmuz 2007