位运算加法
- 统一思路: 首先列出真值表,然后和位运算进行匹配,将真值表变化规则转化为位运算组合
单位加法,当前位只有全0和全1时为0,其他为1,该算法和异或相同,进位只有全1时候为1,其他时候为0,该算法和与相同,因此可以将加法转化为按位异或和按位与的结合
public int add(int a, int b){
int sum = a;
int carry = b;
while (carry != 0){
int tmp = sum;
sum = sum ^ carry;
carry = tmp & carry << 1;
}
return sum;
}
位运算减法
由于负数在计算机内用二进制补码表示,且二进制补码天然可以直接进行加法运算(即将负数采用二进制补码进行编码之后可以像正数一样直接加),因此计算方法和正数相同,代码同上
位运算乘法
包含负数的乘法首先将负数转为正数,并记录符号位,然后移位进行乘法
public int mul(int a, int b){
int sum = 0;
int sig = 1;
if (a < 0){
sig *= -1;
a *= -1;
}
if (b < 0){
sig *= -1;
b *= -1;
}
while (b > 0){
if ((b & 1) != 0){
sum += a;
}
b = b >> 1;
if (b > 0){
sum = sum << 1;
}
}
return sum * sig;
}
位运算除法
作为乘法的逆运算,首先同样将符号位进行记录然后将数字取绝对值,然后将被除数从高位开始逐位取出并右移,当中间结果大于等于除数时候持续减去除数,并将结果自加
public int divide(int dividend, int divisor) {
if (divisor == 0 || dividend == Integer.MIN_VALUE && divisor == -1){
return Integer.MAX_VALUE;
}
int sig = 1 * (dividend > 0 ? 1: -1) * (divisor > 0 ? 1 : -1);
long did = Math.abs((long)dividend);
long div = Math.abs((long)divisor);
long remainder = 0, res = 0;
StringBuffer buffer = new StringBuffer();
while (did > 0){
buffer.append(did & 1);
did >>= 1;
}
char[] data = buffer.reverse().toString().toCharArray();
int len = data.length;
for (int i = 0;i < len;i++){
remainder <<= 1;
if (data[i] == '1'){
remainder |= 1;
}
if (remainder >= div){
remainder -= div;
res |= 1;
}
if (i < len-1){
res <<= 1;
}
}
if (res > Integer.MAX_VALUE){
return Integer.MIN_VALUE;
}
return (int)(res * sig);
}