1.加法
加法其实主要问题是怎么处理进位,当然我们可以每一位分别相加,然后用一个变量来保存下一位是否进位
private static int add(int a, int b) {
int res = 0;
int jinwei = 0;
for(int i = 0 ; i <32 ; i++){
int numA = (a>>i) & 1;
int numB = (b>>i) & 1;
if((numA & numB)>0){
if(jinwei>0){
res |= 1 << i;
}
jinwei = 1;
}else if((numA | numB) > 0){
if(jinwei == 0){
res |= 1<< i;
}
}else{
if(jinwei >0){
res |= 1<<i;
jinwei = 0;
}
}
}
return res;
}
还有一种方法,思想是把进位和每个位之间的运算分开来求,然后再递归求和,直到不再产生进位为止。
private static int add2(int a, int b) {
if( b == 0) return a;
int sum = a^b;
int jinwei = (a&b)<<1;
return add2(sum,jinwei);
}
减法无非就是加上一个数的相反数
2.乘法
a x b ,如果把 b 写成2进制表示,那么就是 ax(b0x2^0) + a x(b1x2^1) ..... 其中bi表示b的2进制中第i位为1或者0,然后我们知道,一个数乘以2的k次方,就是左移k次。
private static int multi(int a, int b) {
int ans = 0;
for(int i = 0; i < 32; i++){
if((b & 1) > 0){
ans = add(ans,a);
}
a<<=1;
b>>=1;
}
return ans;
}
3.除法
除开符号(我们假设2个数都是正数),除法的话,最容易想到的就是,每次减一个除数,看要减多少次使得被除数小于除数,就可以算出结果,但是有一个更快速的方法,例如 11/ 5 , 用二进制表示 1011 / 0101 可以写成 101<<1 + 1 ,起始就是说,有 2<<1 个101, 用上面那个方法我们可以一次性减去 2^k次方个除数。
private static int divide(int a, int b) {
int res = 0;
int num = 0;
for(int i = 31;i>=0 ; --i){
num<<=1;
num |=(a >> i) & 1;
if(num >= b){ //如果当前累计的数大于除数,那么就可以减去除数,此时减去了 2^i次方个除数。
num -= b;
res |= (1<<i);
}
}
return res;
}