1、题目描述
【JZ48】写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/
四则运算符号。
知识点:位运算
难度:☆☆
2、解题思路
知识补充
1、位运算:
操作数1 | 操作数2 | & | | | ^ |
---|---|---|---|---|
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 | 1 |
0 | 0 | 0 | 0 | 0 |
2、原码\反码\补码:
原码:正数最高位为0,负数最高位为1;
反码:正数等于原码,负数除最高位外其他位取反;
补码:正数等于原码,负数为反码加1。
本题分析
本题是考察对位运算的运用,使用位运算来实现两数的加法。
设两数字的二进制形式a
,b
,其求和 s = a + b
,a(i)
代表 a
的二进制第 i
位,则分为以下四种情况:
a(i) | b(i) | 非进位 | 进位 |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 |
1 | 1 | 0 | 1 |
观察发现,“非进位”的结果等同于“异或”运算,“进位”的结果等同于“与”运算,但是需要左移一位,因为“进位”影响下一位的运算。
所以s = a + b
,其实就是“异或”+“与”的结果。
算法步骤:
1、计算a
和b
的“进位”的计算结果,即“与”运算,并左移一位;
2、计算a
和b
的“非进位”的计算结果,即“或”运算;
3、反复1和2,直到“非进位”为0为止。
3、解题代码
package pers.klb.jzoffer.simple;
/**
* @program: JZoffer
* @description: 不用加减乘除符号做加法
* @author: Meumax
* @create: 2020-06-17 11:05
**/
public class AddWithoutTokenSymbol {
public int Add(int num1, int num2) {
int carry = 1;
while (carry != 0) {
// 计算进位,需要左移一位
carry = (num1 & num2) << 1;
// 计算非进位
num1 = num1 ^ num2;
num2 = carry;
}
return num1;
}
}
时间复杂度:O(1)
空间复杂度:O(1)
4、解题心得
这道题第一眼看过去还真的无从下手,看到考点说是位运算,心里有了个大概方向,其实还是不知道如何求解,最后把位运算列出来才发现这个规律,即“非进位”的结果等同于“异或”运算,“进位”的结果等同于“与”运算。
往后遇到再复杂一点的,也知道解题的方向了,往往是列出来,然后找出规律。