位运算实现整数的加减乘数运算

用位运算实现加法也就是计算机用二进制进行运算,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)

相关文章
相关标签/搜索