您的位置:首页 > 其它

【算法题】不使用四则运算求A+B

2018-02-03 18:45 148 查看

题目描述

最近看到一道比较有趣的算法题,原题是这样的:

写一个函数,求两个整数(int)之和,要求在函数体内不得使用+、-、*、/四则运算符号。

我的解法

public int add(int num1, int num2) {
return (num1 & num2) == 0 ? num1 ^ num2 : add(num1 ^ num2, (num1 & num2) << 1);
}


只有一行,很简洁对吧,下面我来慢慢说明思路。

解题思路

这是考察对计算机加法的理解,既然常规的四则运算不能使用,那就要从位运算的角度出发来考虑问题了。

基于二进制加法,现在考虑两种情况

相加不产生进位

当两个二进制相加不产生进位时,A+B与A^B是完全等价的(^表示异或)

举个栗子,9+2

对于加法运算

1 0 0 1

0 0 1 0 +

————

1 0 1 1

对于异或运算

1 0 0 1

0 0 1 0 ^

————

1 0 1 1

因为不产生进位,因此加法的每一位不会对下一位产生影响,而异或正好也是按位运算,二者是等价的。

相加产生进位

这种情况就是在按位异或的基础上与进位相加。进位的条件是两个1相加,因此通过按位与运算(&)就可以找到进位的位置,由于是向高一位进位,所以两数相与后还需要左移一位,最后将相与移位,按位异或的结果相加,这又回到了两数相加的问题,重复递归到两数相加无进位终止即可。

整合的代码如下

public int add(int num1, int num2) {
if ((num1 & num2) == 0) {
//相与为0,不产生进位
return num1 ^ num2;
} else {
//相与不为0,产生进位
return add(num1 ^ num2, (num1 & num2) << 1);
}
}


这种场合下if…else…写法有点low,简化成三目运算符 a? b: c

public int add(int num1, int num2) {
return (num1 & num2) == 0 ? num1 ^ num2 : add(num1 ^ num2, (num1 & num2) << 1);
}


如果觉得递归会给你的效率带来影响,也可以写成循环的形式

public int add(int num1, int num2) {
int temp;
while (num2 != 0) {
temp = num1 ^ num2;
num2 = (num1 & num2) << 1;
num1 = temp;
}
return num1;
}


最后可能有人会问跟负数相加会怎样?

在计算机运算中,由于补码的存在,使得减法既是加法,加减法的计算过程是完全相同的,就算用负数来测试也能得到正确的结果
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 位运算 二进制
相关文章推荐