【筆試題分享】異或與位運算的巧用
第1題
假設x和y都是整數,如果得到其中較小的那個。
微軟2012暑期實習生筆試題。這是道選擇題,從給出的四個選項中選出一個正確的答案。
仔細想想之後,發現A是正確解:y^( (x^y)& -(x<y) )
(現在才認識到異或的神奇之處)
說明自己的理解:
1. 對於(x<y)的判定部分, 如果x<y為真,判斷結果為1, 那麼-(x<y)就得-1(補碼錶示為全1,只考慮8位int型,則為 11111111); 如果x<y為假,判斷結果為0(補碼錶示為 00000000)
2. 對於(x^y),當(x<y)為真時,(x^y)&(11111111) = (x^y);
3. 最後,y^(x^y) = x , 前提是x<y為真;y^0 = y, 前提是x<y為假。
成立。
第2題
最近做的一道筆試題
寫一個巨集定義,實現的功能是將一個int型的數的奇偶位互換,例如6的2進製為0110, 第一位與第二位互換,第三位與第四位互換,得到1001,輸出應該為9 .
完整的程式碼為
#include<iostream>
#include<string>
using namespace std;
#define N(n) ((n<<1)&(0xAAAA))|((n>>1)&(0x5555)) // 此句為解
void main(){
int k=N(6);
cout<<k<<endl;
}
自己的理解:
為簡化說明,以4位二進位制碼為例。
1. 0xAAAA 的二進位制類似於 1010;0x5555 的二進位制類似於 0101
2. (n<<1)&(0xAAAA)
把n先左移1位,再與1010做與運算,只保留移位之後的偶數位的值,奇數位全為0,實際上是隻保留了n的奇數位的值,並把它們交換到了偶數位上。比如 n = 0110 , n<<1 = 1100, (n<<1) & 1010 = 1000 ;
3. (n>>1)&(0x5555)
把n右移一位,再與0101 做與運算,只保留移位之後的奇數位的值,偶數位全為0,實際是隻保留n 的偶數位的值,並把它們交換到對應的奇數位上。n = 0110, n>>1 = 0011, (n>>1) & 0101 = 0001;
4. 最後做或運算, 得1001。
第3題
還有一個關於異或運算的。
如何將a,b的值交換,而不用第三個變數
異或的作用:
a=a^b;
b=a^b;
a=a^b;
即可。