1. 程式人生 > >二進位制移位實現加減乘除

二進位制移位實現加減乘除

1. 題目描述

如何使用位操作分別實現整數的加減乘除四種運算?

2. 解決方案

需要熟練掌握一些常見功能的位操作實現,具體為:

<1> 常用的等式:-n = ~(n-1) = ~n+1

<2> 獲取整數n的二進位制中最後一個1:n&(-n) 或者 n&~(n-1),如:n=010100,則-n=101100,n&(-n)=000100

<3> 去掉整數n的二進位制中最後一個1:n&(n-1),如:n=010100,n-1=010011,n&(n-1)=010000

(1) 加法實現

可以很容易地用“異或”和“或”操作實現整數加法運算:對應位數的“異或操作”可得到該位的數值,對應位的“與操作”可得到該位產生的高位進位,如:a=010010,b=100111,計算步驟如下:

第一輪:a^b=110101,(a&b)<<1=000100, 由於進位(000100)大於0,則進入下一輪計算,a=110101,b=000100,a^b=110001,(a&b)<<1=001000,由於進位大於0,則進入下一輪計算:a=110001,b=001000,a^b=111001,(a&b)<<1=0,進位為0,終止,計算結果為:111001。

程式碼如下:

intadd(inta, intb) { intcarry, add; do{     add = a ^ b;     carry = (a & b) << 1;     a = add;     b = carry;
  }while(carry != 0); returnadd; }

(2) 減法實現

減法可很容易地轉化為加法:a - b = a + (-b) = a + (~b + 1 )

程式碼如下:

intsubtract(inta, intb) { returnadd(a, add(~b, 1)); }

(3) 乘法實現

先看一個例項:1011*1010:

1011    * 1010  ----------     10110 < 左移一位,乘以0010 + 1011000 < 左移3位,乘以1000 ----------   1101110 因而乘法可以通過系列移位和加法完成。最後一個1可通過b&~(b-1)求得,可通過b& (b-1)去掉,為了高效地得到左移的位數,可提前計算一個map,程式碼如下:
intmultiply(inta, intb) { boolneg = (b < 0); if(b < 0)     b = -b; intsum = 0;   map<int,int> bit_map; for(inti = 0; i < 32; i++)     bit_map.insert(pair<int,int>(1 << i, i)); while(b > 0) { intlast_bit = bit_map[b & ~(b - 1)];       sum += (a << last_bit);       b &= b - 1;     } if(neg)     sum = -sum; returnsum; }

(4) 除法實現

乘法可很容易轉化為減法操作,主要思想與乘法實現類似,程式碼如下:

intdivide(inta, intb) { boolneg = (a > 0) ^ (b > 0); if(a < 0)     a = -a; if(b < 0)     b = -b; if(a < b) return0; intmsb = 0; for(msb = 0; msb < 32; msb++) { if((b << msb) >= a) break;   } intq = 0; for(inti = msb; i >= 0; i--) { if((b << i) > a) continue;     q |= (1 << i);     a -= (b << i);   } if(neg) return-q; returnq; }