位操作 ~、&、^、|、>>(>>>)、<<
按位取反(~)
按位取反1取0,0取1
如:01010001 -> 10101110
对13取反:
~13 = 2
解释:
13(十进制) = 1101(二进制)
对1101取反结果为0010所以等于2
按位与(&)
都为1则1,否则为0
如:
1&1=1
1&0=0
0&0=0
1101|1011=1001 =>对应的十进制
13|11=9
按位异或(^)
相同为0,不同为1
如:
1^1=0
1^0=1
1001^1101=0100 =>对应的十进制
13^9=4
使用异或实现不使用第三个值的情况下交换内容
int a = 10, b = 13;
a ^= b;
b ^= a;
a ^= b;
/**
* 结果
* a = 13
* b = 10
*/
按位或(|)
有1则1,否则为0
如:
1|1=1
1|0=1
0|0=0
1101|1011=1111 =>对应的十进制
13|11=15
左右移>>(>>>)、<<
- 右移
>>
:各二进位全部右移若干位,低位(移出的位数)丢弃,高位补符号位(符号位负补1),或者补零(符号位正补0)
如8 >> 2, 8的二进制是0000 1000→右移两位后是00 0010,因为8是整数→高位补两个0得到最终值是0000 0010 = 2(十进制) - 无符号右移
>>>
:各二进位全部右移若干位,高位补零,低位丢弃。无符号右移在java中只对32位和64位的值有意义
如8 >>> 2, 在java中因为8是整形,占4个字节,因此8(00000000 00000000 00000000 00001000)→右移两位高位补0(00000000 00000000 00000000 00000010)结果是十进制2
那-8 >>> 2的结果是多少呢?解析如下,上文我们已经提到“数据在计算机中主要是以补码的形式存储的”,我们都知道正数的补码就是本身;负数的补码是将其对应正数二进制表示所有位(除符号位)取反(0变1,1变0,符号位为1不变)后加1。
-8对应正数8(00000000 00000000 00000000 00001000)→所有位取反(11111111 11111111 11111111 11110111)→加1(11111111 11111111 11111111 11111000)结果是十进制1073741822 - 左移
<<
:各二进位全部左移若干位,高位丢弃,低位补0
如8 << 2, 8的二进制是0000 1000→左移两位后是0010 00→低位补两个0得到最终值是0010 0000 = 32(十进制) - 无符号左移是不存在的,因为左右在低位补位,而低位没有正负数的概念,因此不存在无符号左移
使用左右移实现乘除
int a = 10;
a>>1;//等同于a/2
a<<1;//等同于a*2
//解析
/**
* a<<x;
* a>>x;
* 其中x等同于2的x次方
* x: 1 2 3 4 5
* 2的x次方: 2 4 8 16 32
*/