Java位运算
位运算:只能对整数进行位运算,可加快计算机计算速度。因为所有数在内存中都是以二进制存放,故直接对数的二进制位进行操作非常快,比如乘法、除2操作:通过左右移二进制位即可,无需将数转为十进制后再通过加法完成(乘法本质是由加法实现的)
Java位运算的简单实现:
/* 位运算:加快计算效果,只能对整数进行位运算。因为所有数在内存中都是以二进制存放,故直接对数的二进制位进行操作非常快,
比如乘法、除2操作:通过左右移二进制位即可,无需将数转为十进制后再通过加法完成(乘法本质是由加法实现的)
* */
public class Code1_bitOption {
/* 创建main函数快捷键: 输入psv即可出现提示 */
public static void main(String[] args) {
int a = 7, b = 2;
System.out.println(a + " & " + b + " = " + (a & b));
System.out.println(a + " | " + b + " = " + (a | b));
System.out.println(a + " ^ " + b + " = " + (a ^ b));
System.out.println("~" + a + " = " + (~a));
System.out.println(a + " << " + b + " = " + (a << b));
System.out.println(a + " >> " + b + " = " + (a >> b)); // 带符号右移,最左边高位与符号位保持一致
System.out.println(a + " >>> " + b + " = " + (a >>> b)); // 无符号右移:最左边高位始终填0
}
}
输出:
7 & 2 = 2
7 | 2 = 7
7 ^ 2 = 5
~7 = -8
7 << 2 = 28
7 >> 2 = 1
7 >>> 2 = 1
位运算之2的N次幂、整数转换:
-
问题1:给定一个数,判断是否为2的N次幂
解:关键技巧 a = a &(a-1)能消除a的最低有效位,即消除最右边的1,变为0。
若一个数是2的N次幂,那么它的二进制表示有且只有一个1,如4:010;8:100
故只需判断 a & (a-1)是否为0即可 -
问题2:整数转换。编写一个函数,确定一共需要改变多少个位,才能将整数A转换为整数B
解:找出AB的不同位的个数即为需要改变的位数,通过异或操作能将不同位上变为1,然后再统计1个个数即可。
如何统计一个数的二进制中1的个数?: 使用问题1中的技巧 a = a &(a-1),循环消除a的最右边的1,直到a为0,循环次数即为1的个数.
public class Code2_checkPowerOf2 {
public static void main(String[] args) {
// 控制台输出快捷键, sout + Tab/Enter
System.out.println(checkPowerOfTwo(10));
System.out.println(checkPowerOfTwo(16));
System.out.println(minCountOfBitChange(1, 14));
System.out.println(minCountOfBitChange(2, 3));
}
public static boolean checkPowerOfTwo(int a) {
return (a & (a - 1)) == 0;
}
public static int minCountOfBitChange(int a, int b) {
int temp = a ^ b;
return bitNumOfOne(temp);
}
private static int bitNumOfOne(int x) {
int res = 0;
while (x != 0) {
x &= (x - 1);
res++;
}
return res;
}
}
输出:
false
true
4
1
位运算寻找只出现一次的数
问题:给定一个数组,数组中只有一个数仅出现过一次,其余数都出现过2次,请找出只出现1次的数
解题思路: 使用异或操作,利用其特性:a^a = a, a^0 = 0,且异或操作满足交换律和结合律!!!
public class Code3_singleNum {
public static void main(String[] args) {
int[] nums = new int[]{1, 4, 1, 2, 3, 3, 2};
System.out.println(singleNum(nums));
}
public static int singleNum(int[] nums) {
int res = 0;
for (int i = 0; i < nums.length; i++) {
// 相当于将数组的所有数,与0进行异或操作,然后通过交换律与结合律将2次出现的数异或为0,
// 最后只剩下0与出现1次的数异或,其结果就是该数本身
res ^= nums[i];
}
return res;
}
}
输出:
4