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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Kurozaki_Kun/article/details/79248285

题目描述

最近看到一道比较有趣的算法题,原题是这样的:
写一个函数,求两个整数(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;
    }

最后可能有人会问跟负数相加会怎样?
在计算机运算中,由于补码的存在,使得减法既是加法,加减法的计算过程是完全相同的,就算用负数来测试也能得到正确的结果

猜你喜欢

转载自blog.csdn.net/Kurozaki_Kun/article/details/79248285