2012-09-19 81 views
3

我目前使用BitConverter在signed int中打包兩個unsigned short。此代碼針對不同的值執行數百萬次,我認爲代碼可以進一步優化。這是我目前正在做的 - 你可以假設代碼是C#/ NET。將signed int轉換爲兩個unsigned short用於重構

// to two unsigned shorts from one signed int: 
int xy = 343423; 
byte[] bytes = BitConverter.GetBytes(xy); 
ushort m_X = BitConverter.ToUInt16(bytes, 0); 
ushort m_Y = BitConverter.ToUInt16(bytes, 2); 

// convet two unsigned shorts to one signed int 
byte[] xBytes = BitConverter.GetBytes(m_X); 
byte[] yBytes = BitConverter.GetBytes(m_Y); 
byte[] bytes = new byte[] { 
    xBytes[0], 
    xBytes[1], 
    yBytes[0], 
    yBytes[1], 
}; 
return BitConverter.ToInt32(bytes, 0); 

因此,我發現我可以避免構造數組的開銷,如果我bitshift。但是對於我的生活,我無法弄清楚正確的換擋操作是什麼。我的第一次可憐的嘗試涉及以下代碼:

int xy = 343423; 
const int mask = 0x00000000; 
byte b1, b2, b3, b4; 
b1 = (byte)((xy >> 24)); 
b2 = (byte)((xy >> 16)); 
b3 = (byte)((xy >> 8) & mask); 
b4 = (byte)(xy & mask); 
ushort m_X = (ushort)((xy << b4) | (xy << b3)); 
ushort m_Y = (ushort)((xy << b2) | (xy << b1)); 

有人可以幫我嗎?我想我需要在移位之前屏蔽高位和低位字節。我看到的一些例子包括帶有類型.MaxValue的減法或任意數字,例如負十二,這相當混亂。

**更新**

謝謝你的好的答案。這裏有一個基準測試的結果:

// 34ms for bit shift with 10M operations 
// 959ms for BitConverter with 10M operations 

static void Main(string[] args) 
    { 
     Stopwatch stopWatch = new Stopwatch(); 

     stopWatch.Start(); 
     for (int i = 0; i < 10000000; i++) 
     { 
      ushort x = (ushort)i; 
      ushort y = (ushort)(i >> 16); 
      int result = (y << 16) | x; 
     } 
     stopWatch.Stop(); 
     Console.WriteLine((int)stopWatch.Elapsed.TotalMilliseconds + "ms"); 

     stopWatch.Start(); 
     for (int i = 0; i < 10000000; i++) 
     { 
      byte[] bytes = BitConverter.GetBytes(i); 
      ushort x = BitConverter.ToUInt16(bytes, 0); 
      ushort y = BitConverter.ToUInt16(bytes, 2); 

      byte[] xBytes = BitConverter.GetBytes(x); 
      byte[] yBytes = BitConverter.GetBytes(y); 
      bytes = new byte[] { 
       xBytes[0], 
       xBytes[1], 
       yBytes[0], 
       yBytes[1], 
      }; 
      int result = BitConverter.ToInt32(bytes, 0); 
     } 
     stopWatch.Stop(); 
     Console.WriteLine((int)stopWatch.Elapsed.TotalMilliseconds + "ms"); 


     Console.ReadKey(); 
    } 

回答

5

最簡單的方法是使用兩班制做:

int xy = -123456; 
// Split... 
ushort m_X = (ushort) xy; 
ushort m_Y = (ushort)(xy>>16); 
// Convert back... 
int back = (m_Y << 16) | m_X; 

演示上ideone:link

+0

比我的小。 +1 – spender

+0

在這種情況下,對'uint'的強制轉換不是必需的,因爲當您投射到'ushort'時,您將放棄符號擴展位。 – LukeH

+0

@LukeH你是對的,我編輯了答案,放棄了不必要的演員。 – dasblinkenlight

0
int xy = 343423; 
ushort low = (ushort)(xy & 0x0000ffff); 
ushort high = (ushort)((xy & 0xffff0000) >> 16); 
int xxyy = low + (((int)high) << 16);