位运算基础
- &(与)、|(或)、^(异或)、~ (非 / 取反)
>>
和<<
运算符将二进制为进行右移或者左移操作>>>
运算符将用0填充高位;>>
运算符用符号位填充高位,没有<<<
运算符- 对于int型,1<<35 与 1<<3是相同的
位运算的一些巧妙用法
- 判断奇偶数:x & 1 = 1 为奇数 ,= 0为偶数
- 交换两个整数变量的值
public static void main(String[] args) {
int a = 5;
int b = 3;
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println(a);
System.out.println(b);
}
}
- 获取二进制位是1还是0
public static void main(String[] args) {
int x = 4; //二进制为0100
int y = 3;
System.out.println(x + "的第" + y + "位的二进制位为:" + ( ((x & (1<<(y-1)))>>(y-1)) == 0 ? "0":"1"));
}
}
- 不用判断语句,求整数的绝对值
原理:
将一个整型整数x,带符号右移31位,则结果要么是0,要么是-1。如果是0,则x为正数,为-1则x为负数。
然后,将x与右移31位后的结果做异或运算,当与x^0是,结果还是x。 当x^-1时,结果为x取反,即x的反码,然后+1,即为x的绝对值。
public static void main(String[] args) {
int x = -35;
System.out.println( x>>31 == -1 ? (x ^ (x >> 31))+1 : (x ^ (x >> 31)));
}
}
- 异或,可以理解为不进位加法:1+1=0,0+0=0,1+0=1
1.交换律:可任意交换运算因子的位置,结果不变
2.结合律:(a ^ b)^ c == a ^ (b ^ c)
3.对于任何数x, 都有x ^ x = 0, x ^ 0 = x, 同自己求异或为0,同0求异或为自 己
4.自反性:A ^ B ^ B = A ^ 0 = A。
位运算相关例题
找出唯一成对的数
1-1000这1000个数放在1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将他找出来;不用辅助存储空间,能否设计一个算法实现?
思路
:利用异或的自反性, 将 这个数组 与 除去重复数的所有数 进行异或,最终结果就是那个重复值。
public class Main{
public static void main(String[] args) {
int [] arr = {1,2,3,4,5,6,2};
int x = 0;
//数组内的数进行异或
for(int i=0;i<arr.length;i++)
x ^= arr[i];
//再与1到6数字进行异或
for(int i = 1;i<7;i++)
x ^= i;
System.out.println(x);
}
}
二进制中1的个数
请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。
例:9的二进制表示为1001,有2位是1.
原理:
(x-1) & x,利用该式可循环消去低位的1,循环了多少次,就有多少个1。
public class Main{
public static void main(String[] args) {
int x = 4;
int count = 0;
while(x != 0) {
x = ((x-1) & x);
count++;
}
System.out.println(count);
}
}
是不是2的整数次方
用一条语句判断一个整数是不是2的整数次方。(不考虑负整数次方)
思路:
转化为二进制问题:是否只有一个1,例如001000,0100000等,这种数就是2的整次方数,利用上一个例题的方法就可以解决这个问题。
public class Main{
public static void main(String[] args) {
is2(1024);
is2(1000);
}
public static void is2(int x){
if(((x-1) & x) == 0) {
System.out.println(x + "是2的整数次方!");
}else {
System.out.println(x + "不是2的整数次方!");
}
}
}