位运算实现加减乘除(Java)

1.所有位运算符

&:按位与,对应位都为 1 时结果为 1,否则为 0。
|:按位或,对应位有一个为 1 时结果为 1,否则为 0。
^:按位异或,对应位不同时结果为 1,否则为 0。
~:按位取反,将每一位取反。
<<:左移,将所有位向左移动指定的位数,右边补零。
>>:右移,将所有位向右移动指定的位数,左边补符号位。
>>>:无符号右移,将所有位向右移动指定的位数,左边补零。

2.基本思路

加法:a + b 可以分解为两步:
不考虑进位的部分和 s = a ^ b
只考虑进位的部分 c = (a & b) << 1
然后重复上述过程直到 c = 0 ,此时 s 就是最终结果
减法:a - b 可以转化为 a + (-b) ,而负数在 Java 中是用补码表示的:
补码 = 原码取反 + 1
所以 -b = ~b + 1
然后用加法的方法求 a + (~b + 1)
乘法:a * b 可以分解为多个加法:
对于 b 的每一位 bi ,如果 bi = 1 ,那么就把 a 左移 i 位得到 ai ,然后累加 ai 到结果中
如果 bi = 0 ,那么就跳过这一步
最后得到的累加和就是最终结果
除法:a / b 可以分解为多个减法:
定义一个计数器 count 和一个临时变量 t
每次让 t = b 左移一定的次数 n ,使得 t <= a < t << 1
然后让 a 减去 t ,并让 count 加上 n 的值(相当于2^n)
如果 a >= b ,重复上述过程;如果 a < b ,结束循环
最后得到的 count 就是最终结果

3.示例代码

public class BitOperation{
    // 加法
    public static int add(int a, int b) {
        int s; // 不考虑进位部分和
        int c; // 进位部分

        do {
            s = a ^ b; // 异或得到不考虑进位部分和
            c = (a & b) << 1; // 按与得到进位置,并左移一格

            // 将两者相加(即重复上述过程)
            a = s;
            b = c;
        } while (c !=0); // 直到没有进位置

        return s;

    }

    // 减法(转化成加法)
    public static int sub(int a, int b) {
        return add(a, add(~b,1)); // 负数用补码表示(原码取反+1)
    }

    // 乘法
    public static int mul(int a, int b) {
        int res = 0; // 结果
        while (b != 0) {
            if ((b & 1) == 1) { // 如果 b 的最低位为 1
                res = add(res, a); // 累加 a 到结果中
            }
            a <<= 1; // 将 a 左移一位
            b >>>= 1; // 将 b 右移一位(无符号)
        }
        return res;
    }

    // 除法
    public static int div(int a, int b) {
        int count = 0; // 计数器
        int t; // 临时变量

        while (a >= b) { // 如果被除数大于等于除数
            t = b; // 让 t 等于除数

            while (a >= (t << 1)) { // 如果被除数大于等于 t 左移一位(即乘以2)
                t <<= 1; // 将 t 左移一位(即乘以2)
                count++; // 计数器加一
            }

            a = sub(a, t); // 让被除数减去 t
            count++; // 计数器加一

        }

        return count;
    }
}

猜你喜欢

转载自blog.csdn.net/m0_63748493/article/details/129334160