2015-04-18 20 views
7

Ben 3.5'e .NET 4.0 arasında bir açık kaynak kitaplığı dönüştürmek çalışıyorum ve kolayca aşağıdaki uzun çarpma kodunu dönüştürmek olamaz:C# bir çarpma yüksek bit Bilgisayar

/// <summary> 
    /// Calculate the most significant 64 bits of the 128-bit 
     product x * y, where x and y are 64-bit integers. 
    /// </summary> 
    /// <returns>Returns the most significant 64 bits of the product x * y.</returns> 
    public static long mul64hi(long x, long y) 
    { 
#if !NET35 
     BigInteger product = BigInteger.Multiply(x, y); 
     product = product >> 64; 
     long l = (long)product; 
     return l; 
#else 
     throw new NotSupportedException(); //TODO! 
#endif 
    } 

Gördüğünüz gibi Yazar bunu yapmanın bir yolunu bulamadı. .NET 3.5'de BigInteger bulunmamaktadır.

.NET 3.5 üzerinde 64 bit 64 bit 64 bit yüksek bitleri nasıl hesaplayabilirim?

+0

https://msdn.microsoft.com/en-us/magazine/cc163696.aspx –

+0

teşekkür ederiz: dikkatle ara sonuçlar veya imzalanmamış olup olmadığını kontrol ederek, diğer kadar verimli hale getirilebilir bağlantı için, J # Library kullanarak bunu işe alabilirim! Ben şimdi deniyorum ... – Seneral

+0

hm hayır benim için çalışmıyor, [MDSN] (https://msdn.microsoft.com/de-de/library/7xsxf8e2%28v=vs.90%29.aspx) VS 510 ya da daha az kullanılabilir olduğunu ve diğer sorunlar için (varsayılan parametreler) VS2010 kullanmam gerektiğini söylüyor (varsayılan parametreler) – Seneral

cevap

6

Birden çok N bitli çoğaltıcıdan 2N bitlik bir çoğaltıcı oluşturabilirsiniz.

public static ulong mul64hi(ulong x, ulong y) 
{ 
    ulong accum = ((ulong)(uint)x) * ((ulong)(uint)y); 
    accum >>= 32; 
    accum += (x >> 32) * ((ulong)(uint)y); 
    accum += (y >> 32) * ((ulong)(uint)x); 
    accum >>= 32; 
    accum += (x >> 32) * (y >> 32); 
    return accum; 
} 

Sadece ilkokul uzunluğunda çoğaltma, gerçekten.

İmzalı rakamlarla, biraz daha zordur, çünkü eğer ara sonuçlar işaret bitine taşınırsa her şey ters giderse. Bir long bu olay olmadan 32 bit çarpma tarafından 32 bit sonucunu tutamayacak, bu yüzden daha küçük parçalar halinde bunu yapmak zorunda:

public static long mul64hi(long x, long y) 
{ 
    const long thirtybitmask = 0x3FFFFFFF; 
    const long fourbitmask = 0x0F; 
    long accum = (x & thirtybitmask) * (y & thirtybitmask); 
    accum >>= 30; 
    accum += ((x >> 30) & thirtybitmask) * (y & thirtybitmask); 
    accum += ((y >> 30) & thirtybitmask) * (x & thirtybitmask); 
    accum >>= 30; 
    accum += ((x >> 30) & thirtybitmask) * ((y >> 30) & thirtybitmask); 
    accum += (x >> 60) * (y & fourbitmask); 
    accum += (y >> 60) * (x & fourbitmask); 
    accum >>= 4; 
    accum += (x >> 60) * (y >> 4); 
    accum += (y >> 60) * (x >> 4); 
    return accum; 
} 

Hacker'ın Delight hakkında Harold'ın comment esinlenerek, imzalı versiyon

public static long mul64hi(long x, long y) 
{ 
    ulong u = ((ulong)(uint)x) * ((ulong)(uint)y); 
    long s = u >> 32; 
    s += (x >> 32) * ((long)(uint)y); 
    s += (y >> 32) * ((long)(uint)x); 
    s >>= 32; 
    s += (x >> 32) * (y >> 32); 
    return s; 
} 
+0

Oh, dürüst olmak gerekirse bunun işe yaramasını beklemedim;) Ve gerçekten çözümü kontrol edemiyorum. 4 trilyon (9 trilyon maksimum değeri nedir?) Çok teşekkür ederim! – Seneral

+0

@Seneral: Bir grup ünite testi yaptığınızdan emin olun. Rakamlar imzaladığınız için, ara sonuçların bazıları işaret bitlerine taşıyabilir, sonuçların bozulacağından emin değilim. –

+0

@Seneral: Sanırım negatif sayılar üzerinde çalışması gereken bir versiyonum var. Ekledi –

İlgili konular