2010-09-21 78 views
10

我具有任意8位二進制數例如11101101交換一對位的一個字節

我必須交換的所有對象的比特:

之前交換:11-10-11-01 交換後:11-01-11-10

我在接受採訪時被問到了這個問題!

+0

請告訴我問題嗎? – JamesM 2010-09-21 08:12:08

+0

對不起,我給你的第一個答案,如果它讓你困惑。我完全閱讀你之前/之後的錯誤。 – colithium 2010-09-21 08:18:12

+0

@JamesM:對不起,如果它不明顯,但問題是:在一個字節中,配對比如,如果字節是10101100,那麼將這些比特配對看起來像「10 - 10 - 11 - 00」。現在,如果我們交換單個對,它會變成 - '01 - 01 - 11 - 00'。我需要實現交換的機制 – RaviPathak 2010-09-21 09:13:18

回答

31

在僞碼:

x = ((x & 0b10101010) >> 1) | ((x & 0b01010101) << 1) 

它通過分別處理每個位對低位和高位然後結合結果:

  • 表達x & 0b10101010提取高位,然後>> 1將它移到低位位置。
  • 類似地,表達式(x & 0b01010101) << 1從每對中提取低位並將其移位到高位位置。
  • 然後這兩部分使用按位或組合。

由於不是所有的語言都允許你直接寫二進制文字,你可以把它們寫在例如十六進制:

 
Binary  Hexadecimal Decimal 
0b10101010 0xaa   170 
0b01010101 0x55   85 
+3

鑑於並非所有語言都遵守模式0b ...,所以可能值得注意的是它分別是十六進制的0xAA和0x55。 – userx 2010-09-21 08:29:38

+0

@userx:+1是的,這絕對值得注意。添加。 – 2010-09-21 08:34:06

+0

謝謝馬克。這真棒方法! – RaviPathak 2010-09-21 09:17:59

0
b = (a & 170 >> 1) | (a & 85 << 1) 
+2

這是完全不可讀的;另外,邊緣情況下效率低下,甚至不正確。除以2不等於負數的一位右移。 – tdammers 2010-09-21 08:18:53

+0

與tdammers的答案相同,但是使用十進制數字時,它更清晰明確,二進制。 – vulkanino 2010-09-21 08:21:07

+0

-1非常難讀 – Tomas 2010-09-21 08:29:35

-5

我會第一個代碼它「手寫」 - 也就是在幾個明顯的,明確的階段說,並用它來驗證該單元測試,我在的地方都工作正常,那麼只有轉向更深奧的位操作解決方案,如果我需要性能(並且通過所述改進提供額外的性能)

代碼爲人先,計算機秒。

+1

-1完全不能回答問題 – Tomas 2010-09-21 08:30:06

5
  1. 讓兩位口罩,一個包含所有偶數位並含有一個不均勻的位(1010101001010101)。
  2. 使用按位並將輸入過濾爲兩個數字,一個將所有偶數位置零,另一個將所有不均勻位置零。
  3. 將僅包含偶數位的數字向左移一位,而將另一位向右移一位
  4. 按位或將它們組合在一起。

爲16位(而不是實際的代碼)實施例:

short swap_bit_pair(short i) { 
    return ((i & 0101010110101010b) >> 1) | ((i & 0x0101010101010101b) << 1)); 
} 
+0

嗯..我想你的意思是0xAA,而不是0x10101010(0xAA是10101010,二進制),0x55​​代替0x01010101。反正一個字節。 0xAAAA和0x5555分別爲短。 – userx 2010-09-21 08:24:32

+0

是的,已經編輯了類似於C的僞代碼來使用二進制代替。原來的問題無論如何說8位,所以... – tdammers 2010-09-21 08:30:21

0

最優雅和靈活的解決方案是,正如其他人說,一個「梳」掩模同時適用於偶數和奇數位然後,分別將它們左右移動一個位置,以按位或按比例合併它們。

您可能想要考慮的另一個解決方案是利用相對較小的數據類型。您可以創建256個值,其靜態初始化爲要用作輸出到您的輸入值的查找表:

const unsigned char lookup[] = { 0x02, 0x01, 0x03, 0x08, 0x0A, 0x09, 0x0B ... 

每個值放入數組的代表指數的轉型。所以,如果你再這樣做:

unsigned char out = lookup[ 0xAA ]; 

out將包含0x55

這是更麻煩,比第一種方法不夠靈活(如果你想從8位遷移到16?),但確實有如果執行大量的這些操作,它的速度將顯着提高。

0

假設你的電話號碼是num

首先找到偶數位置位:
num & oxAAAAAAAA

第二步找到奇姿位:
num & ox55555555

第三步改變位置奇位置,甚至位置位和偶數位位奇數位置位:
Even = (num & oxAAAAAAAA)>>1
Odd = (num & 0x55555555)<<1

最後一步...... result = Even | Odd

打印結果