位運算實現整數的加減乘數運算

用位運算實現加法也就是計算機用二進制進行運算,32位的CPU只能表示32位內的數,這裏先用1位數的加法來進行,在不考慮進位的基礎上,以下html

  1. 1 + 1 = 0
  2. 1 + 0 = 1
  3. 0 + 1 = 1
  4. 0 + 0 = 0

很明顯這幾個表達式能夠用位運算的「^」來代替,以下java

  1. 1 ^ 1 = 0
  2. 1 ^ 0 = 1
  3. 0 ^ 1 = 1
  4. 0 ^ 0 = 0

這樣咱們就完成了簡單的一位數加法,那麼要進行二位的加法,這個方法可行不可行呢?確定是不行的,矛盾就在於,如何去獲取進位?要獲取進位咱們能夠以下思考:算法

  1. 0 + 0 = 0
  2. 1 + 0 = 0
  3. 0 + 1 = 0
  4. 1 + 1 = 1
  5. //換個角度看就是這樣
  6. 0 & 0 = 不進位
  7. 1 & 0 = 不進位
  8. 0 & 1 = 不進位
  9. 1 & 1 = 進位

正好,在位運算中,咱們用「<<」表示向左移動一位,也就是「進位」。那麼咱們就能夠獲得以下的表達式ide

  1. //進位能夠用以下表示:
  2. (x&y)<<1

到這裏,咱們基本上擁有了這樣兩個表達式測試

  1. x^y //執行加法
  2. (x&y)<<1 //進位操做

咱們來作個2位數的加法,在不考慮進位的狀況下優化

  1. 11+01 = 100  // 原本的算法
  2.  
  3. // 用推算的表達式計算
  4. 11 ^ 01 = 10
  5.  
  6. (11 & 01) << 1 = 10
  7.  
  8. //到這裏 咱們用普通的加法去運算這兩個數的時候就能夠獲得 10 + 10 = 100
  9. //可是咱們不須要加法,因此要想別的方法,若是讓兩個數再按剛纔的算法計算一次呢
  10.  
  11. 10 ^ 10 = 00
  12.  
  13. (10 & 10) << 1 = 100

到這裏基本上就得出結論了,其實後面的那個 「00」 已經不用再去計算了,由於第一個表達式就已經算出告終果。spa

繼續推理,直至進位補償爲0。.net



/**
	 * 兩個正整數相加
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	public static int aplusb(int a, int b) {
		//用異或模擬不帶進位的加法
		int xor = a ^ b;
		//用按位與模擬是否進位,左移1位表明進位補償
		int and = (a & b) << 1;
		
		//進位補償不斷左移直至爲0,則運算中止
		while (and != 0) {
			//不帶進位加法
			int sum = xor ^ and;
			//得到進位補償
			and=(xor&and)<<1;
			
			xor=sum;
		}
		return xor;
	}
	
	/**
	 * 兩個正整數相加的遞歸算法
	 */
	public static int aplusbPro(int a,int b) {
		if(b==0) {
			return a;
		}
		return aplusbPro(a^b,(a&b)<<1);
	}
	
	/**
	 * 實現整數的相乘
	 */
	public static int amultibPro(int a,int b) {
		int sum=0;
		while(b!=0) {
			if((b&1)!=0)//取最後一位 是否爲0
				sum=aplusb(a,sum);
			a<<=1;
			b>>=1;
		}
		
		return sum;
	}
	
	/**
	 * 遞歸實現整數相乘
	 */
	public static int amultib(int a,int b) {
		return b==1?a:aplusb(amultib(a,b-1),a);//a*(b-1)+a
	}


測試發現:基本的算數運算在計算機底層其實就是經過位運算完成的,所以位運算實現的基本運算的效率和運算符等同code

例如加法運算htm




乘法運算,在計算機底層會對被乘數,乘數作優化。當乘數大於被乘數時,會交替二者的位置,以減小運算次數,提高運算速度

優化前:



優化後




相關文章:1.用位運算實現四則運算之加減乘除

  2.位運算 實現加法

  3.用位運算實現四則運算之加減乘除(用位運算求一個數的1/3)

相關文章
相關標籤/搜索