位逻辑运算
说明 | 备注 | |
A&B | 按位与 | 一个数为假,整个结果为假 |
A|B | 按位或 | 一个数为真,整个结果为真 |
A^B | 异或 | 两个数相等为假,不相等为真 |
~A | 取反 | 一个数为假取反为真,一个数为真取反为假 |
在按位运算中0相当于false,1相当与true
A | B | A&B | A|B | A^B | ~A |
0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 1 | 1 |
1 | 1 | 1 | 1 | 0 | 0 |
位逻辑运算的逻辑结果
A | B | A&B | A|B | A&B |
false | false | false | false | false |
true | false | false | true | true |
false | true | false | true | true |
true | true | true | true | false |
位移运算
说明 | 备注 | |
<< | 左移 | 正书高位移动补0,负数高位移动补1。为保证正数移位后结果为正数,负数移位后为负数 |
>> | 右移 | |
>>> | 无符号右移 | 无论正负数,高位移动补0 |
如:
public class Test {
public static void main(String[] args) {
demoOne();
}
public static void demoOne() {
/**
* 60 二进制 0011 1100
* 13 二进制 0000 1101
*/
int a = 60;
int b = 13;
System.out.println("a&b=\t"+(a & b)+"\t二进制数\t 0000 1100");
System.out.println("a|b=\t"+(a | b)+"\t二进制数\t 0011 1101");
System.out.println("~a=\t"+(~a)+"\t二进制数\t 0000 0011");
System.out.println("a^b=\t"+(a^b)+"\t二进制数\t 0011 0001");
System.out.println("a<<2=\t"+(a<<2)+"\t二进制数\t 1111 0000");
System.out.println("a>>2=\t"+(a>>2)+"\t二进制数\t 0000 1111");
System.out.println("a>>>2=\t"+(a>>>2)+"\t二进制数\t 0000 1111");
}
}
结果为
a&b= 12 二进制数 0000 1100
a|b= 61 二进制数 0011 1101
~a= -61 二进制数 0000 0011
a^b= 49 二进制数 0011 0001
a<<2= 240 二进制数 1111 0000
a>>2= 15 二进制数 0000 1111
a>>>2= 15 二进制数 0000 1111
什么时候使用
我为什么要它?
答案1:位运算的运算效率比直接对数字进行加减乘除高很多(至于为什么会快,不明白的可以去搜下为什么C的代码执行速度比Java,python快),代码需要考虑性能的时候
答案2:因为大牛都喜欢这样,估计是炫技吧!
使用场景
场景1:判断奇偶数 a&1 结果为 0 ,a就是偶数 结果为 1 ,a就是奇数
场景2:求平均数 (x+y)/2 这样吗?考虑过 x+y可能超过int的范围吗?正确的姿势是 (x&y)+((x^y)>>1)
场景3:有两个int类型变量x、y,要求两者数字交换,不用临时变量?(当年学java的时候这可是奥数级别的题目) x ^= y; y ^= x; x ^= y;
场景4:求绝对值
int abs( int x ) { int y= x >> 31 ; return (x^y)-y ; //or: (x+y)^y }
场景5:取模 a % (2^n) 等价于 a & (2^n - 1)
场景6:快速乘法 a * (2^n) 等价于 a << n
场景7:快速除法 a / (2^n) 等价于 a >> n
场景8:求相反数 (~x+1)