SORU
11 HAZİRAN 2013, Salı


Bir çift Yuvarlak için hızlı bir yöntem, bir 32-bit int açıkladı

Lua's kaynak kod okurken, Lua macro double 32-bit int bir tur için kullandığı fark ettim. macro ve bu gibi görünüyor çıkardığım:

union i_cast {double d; int i[2]};
#define double2int(i, d, t)  \
    {volatile union i_cast u; u.d = (d)   6755399441055744.0; \
    (i) = (t)u.i[ENDIANLOC];}

Burada ENDIANLOC büyük indian için, 1 küçük indian endianness, 0 olarak tanımlanır. Lua dikkatle endianness işler. t tamsayı türü, int unsigned int gibi duruyor.

Küçük bir araştırma yaptım ve aynı düşünce kullanan macro daha basit bir biçim var:

#define double2int(i, d) \
    {double t = ((d)   6755399441055744.0); i = *((int *)(&t));}

Ya da bir C -tarzı:

inline int double2int(double d)
{
    d  = 6755399441055744.0;
    return reinterpret_cast<int&>(d);
}

Bu hile herhangi bir makine IEEE 754 hemen hemen her makine bugün anlamına gelir) kullanarak çalışabilirsiniz. Pozitif ve negatif sayılar için çalışır, ve yuvarlama Banker's Rule izler. IEEE 754. izler (çünkü bu şaşırtıcı değildir)

Bunu test etmek için küçük bir program yazdım:

int main()
{
    double d = -12345678.9;
    int i;
    double2int(i, d)
    printf("%d\n", i);
    return 0;
}

Ve beklendiği gibi -12345679, çıktılar.

macro Bu zor işleri nasıl detaylandırmak istiyorum. 6755399441055744.0 aslında ikili 2^51 2^52 ** 23 1.5 sihirli sayı 1.1 olarak temsil edilebilir. 32-bit tamsayı herhangi bir sihirli sayı eklendiğinde, şey, burada kayboldum. Bu hile nasıl çalışır?

P. S: Bu Lua kaynak kodu, Llimits.h.

GÜNCELLEME:

  1. @Mysticial işaret etmektedir, Bu yöntem,bir 32-bit intkendini sınırı yok, ayrıca 64-bit int bir sayı olduğu sürece için genişletilebilir 2^52 aralığıdır. (macro bazı değişikliklere ihtiyacı var.)
  2. Bazı malzemeler bu yöntem Direct3D kullanılabilir.
  3. 86, orada Microsoft çevirici ile çalışan bir hatta zaman daha hızlı macro assembly ile yazılmış (bu da Lua kaynak elde edilir):

    #define double2int(i,n)  __asm {__asm fld n   __asm fistp i}
    
  4. Tek duyarlıklı sayı için benzer bir sihirli numarası vardır: 1.5 * 2 ^23

CEVAP
11 HAZİRAN 2013, Salı


double böyle temsil edilir:

double representation

ve görülen olarak iki 32-bit tamsayı; şimdi, int çekilen tüm sürümleri kodunuzu (diyelim ki bu bir 32-bit int) bu konuda tam rakam, bu yüzden ne yapıyorsun sonunda sadece alarak en düşük 32 bit mantis.


Şimdi, sihirli sayı; doğru ifade, 6755399441055744 2^51 2^52; ekleme gibi bir sayı kuvvetleri double gidin içine "tatlı range" arasında 2^52 ve 2^53, olan, olarak açıkladı Vikipedi here, ilginç bir özelliği vardır:

2 arasında52=4,503,599,627,370,496 ve 253=9,007,199,254,740,992 gösterilebilir numaraları tam olarak gösterilir

Bu mantis 52 bit geniş olmasından kaynaklanır.

Ekleme hakkında başka bir ilginç Gerçek 251252sadece en düşük 32 bit atıyoruz beri zaten atılmış olan en yüksek iki bit - sadece mantis etkiler.


Son ama en az değil: işareti.

IEEE 754 kayan nokta"," 2. tamamlayıcı aritmetik; nasıl bu burada işlenir? makineleri normal tamsayı ise büyüklük ve tabela gösterimi kullanır,

Konuştuk sadece pozitif tamsayılar; şimdi diyelim biz ile ilgili negatif bir sayı aralığı gösterilebilir tarafından bir 32-bit int çok az (mutlak değer) (-2^31 1); Arama -a. Böyle bir dizi açık olumlu sihirli sayı ekleyerek yapılır ve elde edilen değeri 2'dir52251(- ).

Şimdi, biz 2'li mantis tamamlayıcı gösterimi yorumlar varsa ne alabilirim? 2 sonucu topla tamamlayıcı olmalı (252251) (- ). Yine ilk dönem etkiler sadece üst iki biti ne kalır bitleri 0~50 2. tamamlayıcı gösterimi (- ) (yine eksi üst iki bit).

Beri azaltma 2. tamamlayacak sayıda daha küçük bir genişlik yapılır sadece tarafından kesilip ekstra bit sola alarak daha düşük 32 bit verir bize doğru (- ) 32 bit, 2 tamamlayıcı aritmetik.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • FUNKER530 - Veteran Community & Combat Footage

    FUNKER530 -

    25 Ocak 2007
  • jbignacio

    jbignacio

    13 Mart 2006
  • RFS Dan

    RFS Dan

    22 Temmuz 2014