位运算

什么是位运算?

  程序中的所有数在计算机内存都是以二进制的形式存储的。位运算就是直接对整数在内存中的二进制位进行操作

 

位运算概览:

符号 描述 运算规则
& 两个位都为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);

  ⑤:判断某个bit位值是不是1

    给定一个二进制数,若想判断某个bit位的值是不是1,则可将此二进制数与一个同bit值为1,其余位为0的二进制数a做&运算,结果为a,则说明该数bit位为1

    

 

 

二、 | 或运算 

  ①:对一个数据的某些位设置为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.

posted @ 2022-03-22 10:41  杨岂  阅读(162)  评论(0编辑  收藏  举报