位运算的效率是最高的,因为位位运算是直接对二进制进行操作
位运算只能应用于整型和char类型(char类型可以看做是特殊的无符号的整形)
面试题:
a: 判断一个数是否是奇数 a & 1 == 1;
b: 对2 ^ n 取余。 a & (2^n - 1);
c: 如何判断一个数是否是2^n a & (a-1) == 0;
d: 两个整数之间的交换;
e: 用最有效率的方式求2 * 8的值 2 << 3;
a: 判断一个数是否是奇数 a & 1 == 1;
/*
判断一个数是否是奇数?
特点:最低位为1.
a & 1 == 1;
*/
class OperatorDemo1 {
public static void main(String[] args) {
int a = -2018;
// System.out.println(a % 2 == 1);
// System.out.println(a % 2 != 1);
System.out.println((a & 1) == 1);
}
}
b: 对2 ^ n 取余。 a & (2^n - 1);
/*
对2的n次幂取余,都可以转换成位运算。
2^n:
1101 1101
% 0100 0000
1101 1101
& 0011 1111
*/
class OperatorDemo3 {
public static void main(String[] args) {
int a = 2019;
System.out.println(a % 64);
System.out.println(a & (64 - 1));
/*System.out.println(a % 78);
System.out.println(a & (78 - 1));*/
}
}
c: 如何判断一个数是否是2^n
a & (a-1) == 0;
/*
判断一个数是否是2的n次幂?
2^n:因子都是2;
时间复杂度:logn;
能否在常量时间复杂度内, 判断一个数是否是2的n次幂。
2^n的存储特点:只有一个1,后面全部是0.
(a & (a - 1)) == 0
0100 0000
& 0011 1111
0000 0000
0101 0000
& 0100 1111
0100 0000
*/
class OperatorDemo4 {
public static void main(String[] args) {
int a = 1024;
System.out.println((a & (a - 1)) == 0);
}
}
d: 两个整数之间的交换;
/*
面试题
两个整数变量的交换.
*/
class OperatorDemo5 {
public static void main(String[] args) {
// 方式一
/*int a = 4;
int b = 3;
System.out.println("a=" + a + ", b=" + b);
int temp = a;
a = b;
b = temp;
System.out.println("a=" + a + ", b=" + b);*/
// 方式二
// 加法和减法互为逆运算。
/*int a = 4;
int b = 3;
System.out.println("a=" + a + ", b=" + b);
a = a + b; // a = 4 + 3, b = 3;
b = a - b; // a = 4 + 3, b = 4 + 3 - 3 = 4;
a = a - b; // a = 4 + 3 - 4 = 3, b = 4;
System.out.println("a=" + a + ", b=" + b);*/
// 方式三
/*int a = 4;
int b = 3;
System.out.println("a=" + a + ", b=" + b);
a = a ^ b; // a = 4 ^ 3, b = 3
b = a ^ b; // a = 4 ^ 3, b = 4 ^ 3 ^ 3 = 4;
a = a ^ b; // a = 4 ^ 3 ^ 4 = 3, b = 4;
System.out.println("a=" + a + ", b=" + b);*/
// 方式四
int a = 4;
int b = 3;
System.out.println("a=" + a + ", b=" + b);
/*a = a ^ b;
b = b ^ a;
a = a ^ b; */
// a ^= b ^= a ^= b;
a = (a ^ b) ^ (b = a); //工作中千万别这样写, 太show了。写代码,简洁易懂。
System.out.println("a=" + a + ", b=" + b);
}
}
e: 用最有效率的方式求2 * 8的值 2 << 3;
/*
<< 左移: 低位补0,高位丢弃
>> 右移: 高位补符号位, 低位丢弃
>>>无符号右移: 高位补0,低位丢弃
注意事项;
左移:左移n个单位,相当于乘以2^n;
右移: 右移n个单位,相当于除以2^n;
对于移位运算符来说,当操作数超出了字长时,实际移动 n mod 字长 个单位。
练习:
用最有效率的方式写出计算2乘以8的结果
2 << 3
*/
class OperatorDemo7 {
public static void main(String[] args) {
int a = 192;
System.out.println(a << 2); // 192 * 4 = 768
System.out.println(a >> 2); // 192 * 4 = 48
System.out.println(-a >> 2); // -192 * 4 = -48
System.out.println(a >>> 2);// 48
System.out.println(-a >>> 2); // 很大的整数
System.out.println("-----------------------");
a = 64;
System.out.println(a >>> 32);
System.out.println(a << 32);
System.out.println(a >> 32);
System.out.println(a >> 33);
System.out.println(a >> -31);
}
}
/*
192:
0000 0000 0000 0000 0000 0000 1100 0000
<< 2
0000 0000 0000 0000 0000 0011 0000 0000
192:
0000 0000 0000 0000 0000 0000 1100 0000
>> 2
0000 0000 0000 0000 0000 0000 0011 0000
-192:
1111 1111 1111 1111 1111 1111 0100 0000
>> 2
1111 1111 1111 1111 1111 1111 1101 0000
192:
0000 0000 0000 0000 0000 0000 1100 0000
>>> 2
0000 0000 0000 0000 0000 0000 0011 0000
-192:
1111 1111 1111 1111 1111 1111 0100 0000
>>> 2
0011 1111 1111 1111 1111 1111 1101 0000
*/