前言
在讲二进制运算之前,首先得知道原码,反码,补码的概念。举个例子。
二进制运算
- & 按位逻辑与,都为1则为1,否则为0;
- | 按位或,都为0则为0,有一个为1则为1;
- ^ 异或,两个都相同为0,两个不相同为1,11=0,10=1,0^0=0
- ~ 按位取反,包括符号位;
- << 保留符号位,其余的向左移动N位,整数和负数都是低位补0,相当于乘以2的N次方,这种方式用来做2的整数倍乘法运算效率很高。
- .>> 保留符号位,其余的向右移动N位,整数高位补0,负数高位补1
- . >>> 将符号位也一起移动,高位补0,正数跟>>一样,负数因为符号位是1,移动后的结果可能不是我们预期的。
- 对于 int 类型的整数移位 a >> b, 当 b>32 时,系统先用 b 对 32 求余(因为 int 是 32 位),得到的结果才是真正移位的位数,例如,a >> 33 和 a >> 1 的结果相同,而 a >> 32 = a;对于 long 类型的整数移位 a >> b, 当 b>64 时,系统先用 b 对 64 求余(因为 long 是 64 位),得到的结果才是真正移位的位数;当进行移位运算时,只要被移位的二进制码没有发生有效位的数字丢失(对于正数而言,通常指被移出去的位全部是 0),不难发现左移 n 位就相当于乘以 2 的 n 次方,右移 n 位则是除以 2 的 n 次方;
- ~n=-(n+1),3的按位取反 = -4
- -n&n = 整数n的二进制字符串最后一个1所代表的整数,比如-10 & 10 = 2
- == n&(n-1) = 整数n的二进制串去掉最后一个1之后 的整数 ==,比如 10 & 9 = 8
思考题1
int有32位,有什么方法可以判断这个int中有多少位是1?
可以直接用Integer.bitCount函数,也可以自定义一个。
private static int cnt(int value){
int count = 0;
while(value != 0){
value &= (value -1);
count++;
}
return count;
}
测试代码
public static void main(String[] args) {
int a = 10; //00000000000000000000000000001010
int b = -10; //11111111111111111111111111110110
System.out.println("a="+a);
System.out.println("a的二进制表示:");
System.out.println(Integer.toBinaryString(a));
System.out.println("a的二进制表示中1的位数="+Integer.bitCount(a));
System.out.println("a的二进制表示中1的位数="+cnt(a));
System.out.println("=====================");
System.out.println("b="+b);
System.out.println("b的二进制表示:");
System.out.println(Integer.toBinaryString(b));
System.out.println("b的二进制表示中1的位数="+Integer.bitCount(b));
System.out.println("b的二进制表示中1的位数="+cnt(b));
}
结果输出
a=10
a的二进制表示:
1010
a的二进制表示中1的位数=2
a的二进制表示中1的位数=2
=====================
b=-10
b的二进制表示:
11111111111111111111111111110110
b的二进制表示中1的位数=30
b的二进制表示中1的位数=30
Process finished with exit code 0
思考题2
有a,b两个整数,如何用位运算实现a+b??
主要考虑用 位异或(也称不进位加) , 按位与 运算来实现。
public static int add(int a ,int b){
// 异或运算有一个别名叫做:不进位加法
// 那么a ^ b就是a和b相加之后,该进位的地方不进位的结果
// 然后下面考虑哪些地方要进位,自然是a和b里都是1的地方
// a & b就是a和b里都是1的那些位置,a & b << 1 就是进位之后的结果。
// 所以:a + b = (a ^ b) + (a & b << 1)
// 比如:1 + 1 = (1 ^ 1) + (1 & 1 << 1)
// 可以知道,这个过程是在模拟加法的运算过程,进位不可能
// 一直持续,所以b最终会变为0。因此重复做上述操作就可以
// 求得a + b的值。
while (b != 0) {
int bujinwei_jia = a ^ b;
int jinwei = (a & b) << 1;
a = bujinwei_jia;
b = jinwei;
}
return a;
}