【算法题】不使用四则运算求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; }
最后可能有人会问跟负数相加会怎样?
在计算机运算中,由于补码的存在,使得减法既是加法,加减法的计算过程是完全相同的,就算用负数来测试也能得到正确的结果
相关文章推荐
- 【机器学习实战】第11章 使用 Apriori 算法进行关联分析
- 机器学习实战——使用K-近邻算法识别手写数字
- 三大常用机密算法原理与基础使用MD5、3DES、RSA
- 题目:某公司有几万名员工,请完成一个时间复杂度为O(n)的算法对该公司员工的年龄作排序,可使用O(1)的辅助空间。
- 数据结构与算法分析(Java语言描述)(31)—— 使用 Prim 算法求有权图的最小生成树(MST)
- BIRCH算法---使用聚类特征树的多阶段算法
- 使用C++做算法时,对内存的管理的办法
- c#使用椭圆签名算法制作软件序列号
- 验证视图状态 MAC 失败。如果此应用程序由网络场或群集承载,请确保 配置指定了相同的 validationKey 和验证算法。不能在群集中使用 AutoGenerate(正确答案)
- 机器学习笔记(7)---K-近邻算法(5)---使用K近邻算法检测异常操作之二
- 使用logisticregression回归算法训练部分,全部样本 预测良/恶性肿瘤
- 使用局部标准差实现图像的局部对比度增强算法
- 数据结构与算法学习——选择排序【使用上篇的冒泡排序】
- 算法训练 动态数组使用
- 蓝桥杯习题集_ 算法训练 动态数组使用
- 算法导论-6.5-9 使用最小堆完成k路归并算法
- PAT 甲级 1003. Emergency 使用 优先队列 dijkstra 算法
- 【机器学习实战-python3】使用Apriori算法进行关联 分析
- 蓝桥杯 ADV-120算法提高 6-17复数四则运算
- 使用洗牌算法生成随机序列