题目描述:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
暴力解法:
思路:无法使用四则运算符,但是java中有++,--运算符可以使用,找出较小值作为循环次数count,找出较大值作为操作(++,--)对象num,如果count大于0则对num做++,反则--。代码如下:
public static int Add(int num1, int num2) {
int count = (num1 > num2) ? num2 : num1;
int num = (num1 < num2) ? num2 : num1;
if (count < 0) {
for (int i = 0; i > count; i--) {
--num;
}
} else {
for (int i = 0; i < count; i++) {
++num;
}
}
return num;
}
二进制解法:
这里先补充点基础知识,作为后续解题基础
&:称为按位与运算符。它对整型参数的每一个二进制位进行布尔与操作,即两个对应的二进制位同时为1时,才等于1。
|:称为按位或运算符。它对整型参数的每一个二进制位进行布尔或操作,即两个对应的二进制位,任意一个为1时,就等于1。
^:称为按位异或运算符。它对整型参数的每一个二进制位进行布尔异或操作,即两个对应的二进制位,有且仅有一个为1时,才等于1。
~:称为按位非运算符。它是一个单运算符,对运算数的所有二进制位进行取反操作。
<<:称为按位左移运算符。它把第一个运算数的所有二进制位向左移动第二个运算数指定的位数,而新的二进制位补0。将一个数向左移动N个二进制位相当于将该数乘以2的N次方。
>>:称为按位右移运算符。它把第一个运算数的所有二进制位向右移动第二个运算数指定的位数。为了保持运算结果的符号不变,左边二进制位补 0 或 1 取决于原参数的符号位。如果第一个运算数是正的,运算结果最高
位补 0;如果第一个运算数是负的,运算结果最高位补 1。将一个数向右移动N个二进制位相当于将该数除以2的N次方。
高位,指在数据类型限定范围内靠左的二进制位;
低位,指在数据类型限定范围内靠右的二进制位;
符号位,指在数据类型限定范围内最左边的一个二进制位,符号位为0表示正数,1表示负数。
二进制加法:对应位(从低位向高位开始加)相加可能是0,1,2,3 等于2的向前进一位本位为0 等于3的向前进一位本位为1
举例:5+7
0101 5
0111 7
————————————
1100 12
1+1=2 本位0 向前进1
1+0+1(上一位进上来的1)=2 本位0 向前进1
1+1+1(上一位进上来的1)=3 本位1 向前进1
0+0+1(上一位进上来的1)=1 本位1
结果为:1100
思路:
首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111
第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。
第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。
public static int Add1(int num1, int num2) {
while (num2 != 0) {
int temp = num1 ^ num2;
num2 = (num1 & num2) << 1;
num1 = temp;
}
return num1;
}
这里大家可以按照不走在纸上走一下整个过程,这样有利于理解学习。