欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

位运算实现加法和减法——学习笔记

程序员文章站 2022-06-04 11:19:35
...

Leetcode 上看到一道很有意思的题,如何不用“+”和“-”来实现数字的加减运算

既然不能用“+”和“-”,那么只能用位运算来做了,毕竟追本朔源所有的运算都是由位运算实现的。

 

由于二进制每一位只有0和1两个状态,因此每一位只有四种可能的运算,分别是:

(1)0+0=0;

(2)1+0=1;

(3)0+1=1;

(4)1+1=0;

我们找找规律就能发现,其实就是对每一位进行了异或^操作

我们还可以发现只有运算(4)有了进位,由于只有当(1,1)时才有进位,我们可以用与&操作来保存进位。

因此,A+B可以先转化为A^B和A&B两个值,由于A&B是进位值,因此需要整体向前移动一位才算进位,如此一来就得到加法的第一步转化公式:

A+B=A^B+(A&B)<<1;

01+01=00+10;(二进制表示)

 

我们将^和&操作获得的值重新赋给A和B,利用公式不断将A+B进行转化,直到B=0时加法才算完成了。如下:

(1)  A'=A^B;

      B'=(A&B)<<1;

(2)  A=A'

      B=B'

(3)  判断B是否为0,不为0则重新执行(1)

来看个具体的例子:

//任取两数
num1=13;
num2=11;

//二进制
num1: 0 1 1 0 1
num2: 0 1 0 1 1

//位运算操作
x=num1^num2 : 0 0 1 1 0
y=num1&num2 : 0 1 0 0 1

//因为是进位,y要向前移动一位
y=y<<1      : 1 0 0 1 0

//将y当成新的数值继续进行位运算
x2=x^y      : 1 0 1 0 0
y2=x&y      : 0 0 0 1 0

y2=y2<<1    : 0 0 1 0 0

x3=x2^y2    : 1 0 0 0 0
y3=x2&y2    : 0 0 1 0 0

y3=y3<<1    : 0 1 0 0 0

//当y=0时结束
x4=x3^y3    : 1 1 0 0 0
y4=x3&y3    : 0 0 0 0 0

看起来好像有点复杂,其实只是不断重复相同的几个操作罢了。当A&B等于0时,说明已经不需要进位了,此时已经得到了正确的值了。来看看具体的代码:

int Addition(int num1, int num2) {
	int x = num1 ^ num2;
	int y = num1 & num2;

	while (y != 0) {
		y = y << 1;
		int temp = x;
		x = x ^ y;
		y = temp & y;
	}

	return x;
}

加法搞定,减法其实就不需要写了,毕竟 A-B=A+(-B) 。当然也可以作为练习推一推减法,代码如下:

int Subtraction(int num1, int num2) {
	int x = num1 ^ num2;
	int y = x & num2;

	while (y != 0) {
		y = y << 1;
		x = x ^ y;
		y = x & y;
	}

	return x;
}

 减法似乎更加简洁?当然减法加法只要写一个即可。

当然这里还有个问题,由于不能用“-”,所以当遇到A-B=A+(-B)时,我们也没法像以前那样随便用“-”得到相反数了,根据整型数据的性质我们可以知道:

位运算实现加法和减法——学习笔记

取相反数就相当于:

-B=~B+1

看代码:

int Opposite(int num) {
	return Addition(~num,1);
}

//or

int Opposite(int num) {
	return Subtraction(~num,-1);
}

 

相关标签: bit add