我覺得比較難想的是加法吧。
首先加法,腦海中腦補二進制加法,相同位相加,超過2 ,則進1,留0
那么用位運算怎么實現呢?其實理解了異或和與操作,就很容易想出來了。
我覺得異或操作和與操作完全就是實現加法的。 異或就是相同位相加最后留下的結果,而與就是相同位相加是否進1的結果。
異或:相同位 相同為0,不同為1。
與:相同位 都是1結果才是1,否則都是0。
這不就是二進制相加嗎?
異或 與
1+1 = 0 進1
1+0 = 1 進0
0+0= 0 進0
所以加法就是,每次先異或一下,然后算出來進位的結果,再左移一位,因為是進位嘛
static int Add(int x, int y)
{
while (y != 0)
{
int z = x;
x ^= y;
y &= z;
y <<= 1;
}
return x;
}
減法,就很容易實現了,減一個數等於加上這個數的負數
一個數怎么變成負數呢?取反碼然后+1
所以減法就是
static int Sub(int x, int y)
{
int z = Add(~y, 1);
return Add(x, z);
}
那么乘法呢,簡單的想法是,一個一個想加唄,a* b不就是b個a相加,對不對,想法的是對的,但是我們要利用二進制的思想,也就倍增的思想。
任何兩個數相乘可以看成,舉個例子
15 * 19
= 15 * 1 + 15 * 2 + 15 * 16
而15 * 1 就是 15 << 0
15 * 2 就是 15 << 2
所以原本要加19次的,現在變成了加三次,並且每次向左移動一位就可以了。
那么怎么把19 變成 16 + 2 + 1呢?
很簡單,for 循環,看代碼吧
static int Multiply(int x, int y)
{
int res = 0;
for (int i = 30; i >= 0; i--)
{
if ((1 << i) <= y)
{
res = Add(res, x << i);
y = Sub(y, 1 << i);
}
if (y == 0)
break;
}
return res;
}
除法和乘法類似,我們可以用倍增的思想,任何數字都可以由2^x+2^y+2^z......組成的。
所以我們用被除數減去 除數*2^x ,那么商就+= 2^x ,然后減去得到差,繼續再減 除數的2^x
c++
static int Dev(int x, int y)
{
int res = 0;
for (int i = 30; i >= 0; i--)
{
if (y << i <= 0) continue;
if (y << i <= x)
{
res = Add(res, 1 << i);
x = Sub(x, y << i);
}
if (x == 0)
break;
}
return res;
}
最后再補充位運算一個有趣的網站
http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog