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

用位运算实现加法也就是计算机用二进制进行运算,32位的CPU只能表示32位内的数,这里先用1位数的加法来进行,在不考虑进位的基础上,如下

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

很明显这几个表达式可以用位运算的“^”来代替,如下

  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 = 进位

正好,在位运算中,我们用“<<”表示向左移动一位,也就是“进位”。那么我们就可以得到如下的表达式

  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” 已经不用再去计算了,因为第一个表达式就已经算出了结果。

继续推理,直至进位补偿为0。



	/**
	 * 两个正整数相加
	 * 
	 * @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
	}


测试发现:基本的算数运算在计算机底层其实就是通过位运算完成的,因此位运算实现的基本运算的效率和运算符等同

例如加法运算




乘法运算,在计算机底层会对被乘数,乘数做优化。当乘数大于被乘数时,会交替两者的位置,以减少运算次数,提升运算速度

优化前:



优化后




相关文章:1.用位运算实现四则运算之加减乘除

  2.位运算 实现加法

  3.用位运算实现四则运算之加减乘除(用位运算求一个数的1/3)


原文地址:https://www.cnblogs.com/chenny3/p/10226126.html