二进制
二进制是计算机中一种常用的计数系统,也是现代计算机的基石,计算机中的所有信息都是以二进制形式表示的,而计算机的一切操作也都是以二进制进行的。因此学习和掌握二进制及其相关运算,对理解计算机工作原理以及优化算法具有重要意义。
位运算
由于计算机中数据都是以二进制的形式存在的,那么对二进制位进行直接操作,必定能够使算法更为高效,位运算便应运而生。
位运算的基本类型
按位与:两个位都为1时,结果才为1
按位或:两个位都为0时,结果才为0
按位异或:两个位相同时,结果为1,否则结果为0
取反:对各个位分别取反(0变为1,1变为0)
左移:将各二进制位左移若干位,高位(左边)舍弃,低位(右边)补0
右移:将各二进制位右移若干位,低位(右边)舍弃,正数时高位(左边)补0,负数时高位(左边)补1
位运算的性质
按位与:
与0相与清零。想将指定位上的数清零,只需与一个相应指定位上为0的数相与即可。
与1想与保留原值。想获取(或保留)指定位上的数,只需找一个相应指定位为1,其余位为0的数相与即可
如:将10111100 11011111的低八位清零 高八位保留,只需要将其与11111111 00000000相与即可
按位或:
与0相或保留原值
与1相或将指定位置置1
如:将10110010的低四位置为1,只需将其与1111相或即可,即:10110010|1111=10111111
按位异或:
与0异或保留原值
与1异或将指定位置翻转
如:将11001011低四位翻转,只需将其与1111相异或即可,即:11001011^1111=11000100
左移运算:
相当于将原数值乘以2(注意溢出)
右移运算:
相当于将原数值除以2
位运算的应用技巧
判断奇偶性
奇数的二进制数末位为1,偶数的二进制位末位为0,因此可以将给定的数与1相与,结果为0则为偶数
public static boolean isPower(int i) {
return (i & (i - 1)) == 0;
}
判断是否是2的整数幂
表1
由上表可以看出,要判断一个数是否是2的整数幂,只需将该数与该数减1相与,若结果为0,则说明这个数是2的整数次幂
将表1前几列累加得到表2,可以看出,每次进行运算n&(n-1),都消掉一个"1",因此只要计算当最终结果为0时执行的次数即可。
public static int countBit(int i) {
int count = 0;
while (i != 0) {
count++;
i &= i - 1;
}
return count;
}
最后附上最近使用位运算优化求解最大公约数的一个算法
public static int gcd(int a, int b) {
if (a == b) {
return a;
}
if (a < b) {
return gcd(b, a);
}
if (isEven(a) && isEven(b)) {
return gcd(a >> 1, b >> 1) << 1;
}
if (isEven(a) && !isEven(b)) {
return gcd(a >> 1, b);
}
if (!isEven(a) && isEven(b)) {
return gcd(a, b >> 1);
}
if (!isEven(a) && !isEven(b)) {
return gcd(b, a - b);
}
return -1;
}