1. 位运算
位运算起源于C语言的低级操作,Java的设计初衷是嵌入到电视机顶盒内,所以这种低级操作方式被保留下来。所谓的低级操作,是因为位运算的操作对象是二进制位,但是这种低级操作对计算机而言是非常简单直接,友好高效的。在简单的低成本处理器上,通常位运算比除法快得多,比乘法快几倍,有时比加法快得多。虽然由于较长的指令流水线和其他架构设计选择,现代处理器通常执行加法和乘法的速度与位运算一样快,但由于资源使用减少,位运算通常会使用较少的功率,所以在一些Java底层算法中,巧妙的使用位运算可以大量减少运行开销。
2. 位运算符
- 按位与运算符(&):两个位都为1时,结果才为1。
- 按位或运算符(|):两个位都为0时,结果才为0。
- 异或运算符(^):两个位相同为0,不同为1。
- 取反运算符(~):0变1,1变0。
- 左移运算符(<<):各二进制位全部左移若干位,高位丢弃,低位补0。
- 右移运算符(>>):各二进制位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)。
3. 按位与运算符
- 定义:参与运算的两个数据,按二进制位进行“与”运算
- 规则:0&0=0 0&1=0 1&0=0 1&1=1
- 总结:两位同时为1结果才为1,否则为0
- 注意:负数按补码形式参与按位与运算
3.1 清零
- 如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为0的数值相与,结果为0。
- 10100010 & 00000000 = 00000000
3.2 取一个数的指定位
- 取X的指定位,只需要找一个数Y,令Y的指定位为1,其余为为0,将X与Y进行按位与运算即可得X的指定位。
- 取X=10011100的低四位,令Y=00001111,则X的第四位为10011100 & 00001111 = 00001100
3.3 判断奇偶
- 根据末位为0还是1来决定
- if((a & 1) == 0) ? “偶数” :“偶数”
4. 按位或运算符
- 定义:参与运算的两个数据,按二进制位进行"或"运算。
- 规则:0|0=0 0|1=1 1|0=1 1|1=1
- 总结:参与运算的两个数据有一个为1,结果就为1。
- 注意:负数按补码形式参与按位"或"运算。
4.1 设置指定位为1
- 设置X的指定位为1,只需要找到一个数Y,令Y的指定位为1其余为为0,将X与Y进行按位或运算即可使X指定位为1。
- 设置X=10010011的低四位为1,令Y=00001111,则X | Y = 10011111
5. 异或运算符
- 定义:参与运算的两个数据,按二进制位进行"异或"运算。
- 规则:0^0=0 0^1=1 1^0=1 1^1=0
- 总结:参与运算的两个数据,如果位数相同为1,不同为0。
- 性质:
- 交换律:a ^ b = b ^ a
- 结合律:a ^ b ^ c = (a ^ b) ^ c = a ^ (b ^ c)
- 对于任何数x,都有 x ^ x = 0,x ^ 0 = x
- 自反性:a ^ b ^ b = a ^ 0 = a
5.1 翻转指定位
- 翻转X的指定位为1,只需找到一个数Y,令Y的指定位为1,其余各位为0,将X与Y进行异或运算即可翻转X指定位。
- 翻转X=10010011低四位为1,令Y=00001111,则X ^ Y = 1001100
5.2 交换两个数
- 交换a=12和b=15两个数
public class ChangeNumber
{
public static void main(String[] args)
{
int a = 12;
int b = 15;
a ^= b;
b ^= a;
a ^= b;
System.out.println("a = " + a);
System.out.println("b = " + b);
}
}
6. 取反运算符
- 定义:参与运算的一个数据按二进制位进行"取反"运算。
- 规则:~0 = 1 ~1 = 0
- 总结:对一个二进制位进行取反运算,即0变1,1变0。
6.1 使一个数最低位为0
- 使a的最低位为0,则可以令a & ~1
7. 左移运算符
- 定义:将一个运算数据的各二进制位全部左移若干位,左边的二进制位丢弃,右边二进制位补0。
- 总结:若左移过程中舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
- 规则:设X=10101110,令X=X<<2,则X=10111000
8. 右移运算符
- 定义:将一个运算数据的各二进制位全部右移若干位,右边的二进制位丢弃,正数左补0,负数左补1。
- 总结:操作数每右移一位,相当于该数除以2
<<2,则X=10111000
8. 右移运算符
- 定义:将一个运算数据的各二进制位全部右移若干位,右边的二进制位丢弃,正数左补0,负数左补1。
- 总结:操作数每右移一位,相当于该数除以2
- 规则:设X=10101110,令X=X>>2,则X=11101011