通过位运算来实现基本四则运算

位运算加法


  • 统一思路: 首先列出真值表,然后和位运算进行匹配,将真值表变化规则转化为位运算组合

单位加法,当前位只有全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);
    }

你可能感兴趣的:(算法小记)