什么是位运算?
程序中的所有数在计算机内存都是以二进制的形式存储的。位运算就是直接对整数在内存中的二进制位进行操作
位运算概览:
符号 | 描述 | 运算规则 |
---|---|---|
& | 与 | 两个位都为1时,结果才为1 |
| | 或 | 两个位都为0时,结果才为0,有一个位为1,结果即为1 |
^ | 异或 XOR | 两个位相同为0,相异为1 |
~ | 取反 | 0变1,1变0 |
<< | 左移 | 各二进位全部左移若干位,高位(最左位)丢弃,低位补0 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) |
>>> | 无符号右移 | 又称逻辑右移,不管正负,高位补0 |
一、& 与运算
①:判断一个数是不是2的次幂
思路:凡是2的整数次幂和它本身减1的结果进行&运算的结果都必然是0,反之,必然不是0。
public static boolean is2Power(int a) {
return (a & a - 1) == 0;
}
②:判断一个数是不是偶数
思路:偶数和1做与&运算为0
根据二进制位最末位是0还是1来判断,为0就是偶数,为1就是奇数,因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数
③:清零
思路:清零即把其全部二进制位置为0,只要与一个全部二进制位都是0的数值&运算,结果则为0。n&0=0
④:取余(索引计算)
当一个 int 值是a的二次幂的时候,h&(a-1) = h%a
如HashMap中计算索引的代码:
int index=h&(INITIAL_CAPACITY-1); //假设INITIAL_CAPACITY为16 1001 1011 //155 & 1111 //16-1 —————————— 1011 //直接舍弃前面N位,取后4位,特别的高效
Netty时间轮HashedWheelTimer计算延时任务时间格的代码:
# ticksPerWheel取整为2的次幂 int mask = ticksPerWheel - 1; // 计算时间轮指针当前指向的槽位,tick为指针总的转动次数 int idx = (int) (tick & mask);
二、 | 或运算
①:对一个数据的某些位设置为1
比如将数 X=1010 1110 的低4位设置为1,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位或运算(X|Y=1010 1111)即可得到
三、^ 异或运算
两个相同的数异或之后的结果为0:n^n=0,并且任何数与0异或之后等于它本身:n^0=n
①:判断两个数是否相等
两个相同的数异或之后的结果为0:n^n=0
也可用于找出没有重复的数,如一组整型数据中,只有一个数出现了一次,其他的数都出现了两次,要找出这个数,可以将所有的数做异或运算,因为出现两次的数做运算结果为0,因此最终的结果就是那个没有重复的数
②:交换两个数
void Swap(int &a, int &b){ if (a != b){ a ^= b; b ^= a; a ^= b; } }
因为:a^b^b=a
③:翻转指定位
比如将数 X=1010 1110 的低4位进行翻转,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行异或运算(X^Y=1010 0001)即可得到
④:与0相异或值不变
任何数与0做异或运算结果等于其本身,例如:1010 1110 ^ 0000 0000 = 1010 1110
END.