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;
}
}