2013-10-24 23 views
4

隨着各種渠道的幫助下端互換,我已經寫在我的二進制讀取類的一些SwapBytes方法,在ushort交換端,uintulong,全部採用按位操作都在原C#有沒有必要任何unsafe的代碼。按位各類

public ushort SwapBytes(ushort x) 
{ 
    return (ushort)((ushort)((x & 0xff) << 8) | ((x >> 8) & 0xff)); 
} 

public uint SwapBytes(uint x) 
{ 
    return ((x & 0x000000ff) << 24) + 
      ((x & 0x0000ff00) << 8) + 
      ((x & 0x00ff0000) >> 8) + 
      ((x & 0xff000000) >> 24); 
} 

public ulong SwapBytes(ulong value) 
{ 
    ulong uvalue = value; 
    ulong swapped = 
     ((0x00000000000000FF) & (uvalue >> 56) 
     | (0x000000000000FF00) & (uvalue >> 40) 
     | (0x0000000000FF0000) & (uvalue >> 24) 
     | (0x00000000FF000000) & (uvalue >> 8) 
     | (0x000000FF00000000) & (uvalue << 8) 
     | (0x0000FF0000000000) & (uvalue << 24) 
     | (0x00FF000000000000) & (uvalue << 40) 
     | (0xFF00000000000000) & (uvalue << 56)); 
    return swapped; 
} 

我將如何去創造同樣的方法,但對於這些類型的,如短,int和長的簽名的版本,使用上述只是同樣的方法,以及如何改善可以被製成上面的方法?

+0

爲什麼你需要擺在首位交換?難道你不能直接從輸入字節數組中使用期望的字節順序來讀取嗎?根據我的經驗,這會導致更快,更易於閱讀和更容易測試代碼。 – CodesInChaos

回答

12

相反的概念解構到單獨的字節,然後重新組裝周圍他們其他的方式,你可以在概念上交換字節組,像這樣的:(未測試)

public uint SwapBytes(uint x) 
{ 
    // swap adjacent 16-bit blocks 
    x = (x >> 16) | (x << 16); 
    // swap adjacent 8-bit blocks 
    return ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8); 
} 

沒有太大的幫助(或所有)爲32位,但它確實是64位(未測試)

public ulong SwapBytes(ulong x) 
{ 
    // swap adjacent 32-bit blocks 
    x = (x >> 32) | (x << 32); 
    // swap adjacent 16-bit blocks 
    x = ((x & 0xFFFF0000FFFF0000) >> 16) | ((x & 0x0000FFFF0000FFFF) << 16); 
    // swap adjacent 8-bit blocks 
    return ((x & 0xFF00FF00FF00FF00) >> 8) | ((x & 0x00FF00FF00FF00FF) << 8); 
} 

對於符號類型,只是轉換爲無符號,這樣做,那麼投退。

+0

*請*保留評論。我知道在弄清楚這些掩飾和轉移是否合適之前,我會感到非常困惑。 –

+0

不錯!並...測試:http://ideone.com/RZeKlC –

5

你應該有一個看看下面的MSDN頁:http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

您可以簡單地使用Array.Reverse和bitConverter:

int value = 12345678; 
    byte[] bytes = BitConverter.GetBytes(value); 

    Array.Reverse(bytes); 
    int result = BitConverter.ToInt32(bytes, 0); 
+0

正如我所說的,我想使用按位運算符而不是在類型之間轉換並在數組之間交換 – bizzehdee

+1

這肯定會比OP給出的代碼慢得多。你可以對它進行基準測試並查看 –

+2

'BitConverter'使用原生的字節順序,速度很慢,'Array.Reverse'傳播一個不必要的實例,使其更慢。 – CodesInChaos

2

就在開始鑄造添加到無符號和回在簽署結束。

public long SwapBytes(long value) 
{ 
    return (long)SwapBytes((ulong)value); 
} 

這可能需要手動內聯爲最大性能調用SwapBytes


在不同的音符,你可能想避免交換,有利於從所需的字節順序的原始字節數組直接讀取數據。有關詳細信息,請參閱Efficient way to read big endian data in C#

-1

這可能是一個整數,以取代位的最簡單和懶惰的方式:

using System; 

namespace BitSwap 
{ 
    class Program  
    { 
    static void Main()   
    { 
     //swaps bits {p, p+1, …, p+k-1} with bits {q, q+1, …, q+k-1} of n. 
     Console.WriteLine("n="); 
     uint n = uint.Parse(Console.ReadLine()); 
     Console.WriteLine("p="); 
     int p = int.Parse(Console.ReadLine()); 
     Console.WriteLine("q="); 
     int q = int.Parse(Console.ReadLine()); 
     Console.WriteLine("k="); 
     int k = int.Parse(Console.ReadLine()); 
     int i; 
     int s; 
     if ((p + k - 1) < 32 && (q + k - 1) < 32 && p > 0 && q > 0) 
     // for integer 
     { 
      for (i = p, s = q; i <= p + k - 1 && s <= q + k - 1; i++, s++) 
      { 
       uint firstBits = (n >> i) & 1; 
       uint secondBits = (n >> s) & 1; 
       uint maskFirstBits = (uint)1 << i; 
       uint maskSecondBits = (uint)1 << s; 
       n = (n & ~maskFirstBits) | (secondBits << i); 
       n = (n & ~maskSecondBits) | (firstBits << s); 
      } 
      Console.WriteLine("Result: {0}", n); 
     } 
     else 
     { 
      Console.WriteLine("Invalid entry."); 
     } 
    } 
    } 
}