不使用运算符 + 和 - ,计算两整数 a 、b 之和。
题目说不能使用运算符 + 和 -,那么可以使用其他方式来替代两个运算符的功能。
位运算
我们平常开发中位运算使用的并不多,但如果能巧妙使用位运算可以减少运行开销和优化算法,比如Java源码里面的HashMap就有位运算。
单位换算
bit:位。一个二进制数据0或1,是1bit
byte:字节。1 byte = 8 bit,存储空间的计量单位
一个英文字符占一个字节。
一个汉字占两个字节。
支持的数据类型
首先明确一点,Java中的位运算是针对整形的数据类型进行运算的,所以操作数必须是以下五种之一:byte、short、int、long、char
位运算符
| & | 按位与 |
| | | 按位或 |
| ~ | 按位非 |
| ^ | 按位异或 |
| << | 左移 |
>> | 右移 |
| <<< | 无符号右移 |
按位与 &
| 操作 | 十进制 | 二进制 | |
|---|---|---|---|
| 操作数1 | 3 | 0 0 1 1 | |
| 操作数2 | 5 | 0 1 0 1 | |
| & 后结果 | 1 | 0 0 0 1 |
总结:对应位同为1,才为1,否则全为0。
另外:你可以把1理解为true,把0理解为false, true和false进行与(&)时,必须同为true时结果才为true。
按位或 |
| 操作 | 十进制 | 二进制 | |
|---|---|---|---|
| 操作数1 | 3 | 0 0 1 1 | |
| 操作数2 | 5 | 0 1 0 1 | |
| | 后结果 | 7 | 0 1 1 1 |
总结:对应位只要有1时,即为1,否则全为0(对应位只有全是0时,结果才是0,否则为1)。
另外:你可以把1理解为true,把0理解为false, true和false进行或(|)时,只要有true,结果即为true。
按位非 ~
| 操作 | 十进制 | 二进制 | |
|---|---|---|---|
| 操作数1 | 3 | 0 0 1 1 | |
| ~ 后结果 | 12 | 1 1 0 0 |
总结:对每位进行取反。
按位异或 ^
| 操作 | 十进制 | 二进制 | |
|---|---|---|---|
| 操作数1 | 3 | 0 0 1 1 | |
| 操作数2 | 5 | 0 1 0 1 | |
| ^ 后结果 | 7 | 0 1 1 0 |
总结:只要对应为不同即为1。
左移 << 和 右移 >>
m<<n即在数字没有溢出的前提下,对于正数和负数,左移n位都相当于m乘以2的n次方。
m>>n即相当于m除以2的n次方,得到的为整数时,即为结果。如果结果为小数,此时会出现两种情况:
如果m为正数,得到的商会无条件 的舍弃小数位;
如果m为负数,舍弃小数部分,然后把整数部分加+1得到位移后的值。
无符号右移 >>>
无符号右移>>> 与 右移>> 的区别就是无论操作数是正数还是负数,高位都是补0。
恩,基础知识暂时讲解这么多,下面回归本题加法实现。
加法实现
对于二进制的整数加法来说,我们需要让 1 和 0 的运算结果为 1,而 0 和 0的运算结果为 0。这和 异或 运算的结果刚好相同。
1 ^ 0 = 1, 0 ^ 0 = 0同时,我们需要让 1 和 1的运算结果为 10,也就是需要进位,很明显无法使用单次的位运算操作实现,因为我们可以考虑通过 与 运算和 移位 运算来实现。
(1 & 1) << 1 = 10和竖式加法一样,如果两个数相加不发生进位,那么直接用 异或 就足够了,如果发生进位,那么我们需要将 异或 的结果和 进位 的结果相加。
java 代码实现
public int getSum(int a, int b) {
int sum = a, carry = b;
while (carry != 0) {
int temp = sum ^ carry;
carry = (sum&carry)<<1;
sum = temp;
}
return sum;
}如果觉得写的不错,求关注、求点赞、求转发,如果有问题或者文中有错误,欢迎留言讨论。
转载请注明出处。
扫描关注公众号,第一时间获得更新