位运算

数据在计算机中都是以01的形态进行存储,位运算可以直接对01进行操作,其效率自然很高,在Java源码中是很常见的。这里总结位运算的概念以及常见的操作,后续遇到会补充。

位运算符

位运算是需要使用位运算符的,位运算符有如下几种(本表以java语言中的位运算为标准):

含义 符号 简述
按位与 a & b 同一得 1
按位或 a | b 有一得 1
按位异或 a ^ b 相同得 0
按位取反 ~a 取反
左移 a << b 向左移动,低位补零,高位舍弃
带符号右移 a >> b 向右移动,高位补原有高位,低位舍弃
无符号右移 a >>> b 忽略符号位,空位都以0补齐

位运算优先级

~的优先级最高,其次是<<、>>和>>>,再次是&,然后是^,优先级最低的是|。

位运算符在日常开发中也是 有许多应用场景的,具体场景将在下边代码中展示:

按位或 |

/**
 * | 按位或 有一得1
 * 比较m, n之间,换成二进制后谁的1最多
 * 使用 按位或 | 计算 有一得一,与&清零不同的是使用 | 可以置1
 * @param m
 * @param n
 */
public static int  test2(int m ,int n) {
        // 7:111 8:0001 7|8 = 111(2) | 0001(2) = 1111(2) = 15
        // 6:011 7:111 6|7 = 011(2) | 111(2) = 111(2) = 7
        while ((m | m+1)<=n) {
            m = (m | m+1);
        }
        return m;
}

按位与 &

/**
 *  & 按位与 同一得1
 * 判断一个整数n是不是2的x次幂
 * 若n&(n-1)=0 则说明n是2的x次幂
 * 也可以这样说:循环结束后当ans=1时,说明n时2的x幂
 * 按位与 & : 同一得一,可用于清零操作
 * @param n 
 * @return ans  表示n转化成二进制数之后,1的个数
 */
public static int test1(int n) {
    int ans = 0;
    while (n != 0) {
        ans++;
        n &= (n-1);
        System.out.println(n);
    }
    return ans;
}

异或 ^

/**
 * ^ 异或 相同得0
 * 可用于交换两个变量的数值,不用到带三个变量
 * 交换律
 * @param a , b
 */
public static void test3(int a, int b) {
    a = a ^ b;
    // a^b ^ b = a
    b = a ^ b;
    // a^b ^ a = b
    a = a ^ b;
}

按位取反~

 /**
  * 取反 ~
  * 先对原数进行按位取反,然后减1,再进行取反得到一个数,最后加上负号即可
  *
  * 00000000 00000000 00000000 00000100 原值
  * 11111111 11111111 11111111 11111011 取反
  * 11111111 11111111 11111111 11111010 -1
  * 00000000 00000000 00000000 00000101 取反
  */
 public static void test4() {
     int a = 4;
     System.out.print(~4);
 }

左移 <<

/**
 * 左移 <<
 * 
 * 00000000 00000000 00000000 00000101 左移2位后,低位补0
 * 00000000 00000000 00000000 00010100 转为十进制为 20
 */
public static void test5() {
    int a = 5;
    System.out.print(a << 2);
}

右移 >>

/**
 * 右移 >> 高位补符号位 
 * 
 * 00000000 00000000 00000000 00000101 右移2位后,高位补0
 * 00000000 00000000 00000000 00000001 转为十进制为 1
 */
public static void test6() {
    int a = 5;
    System.out.print(a >> 2);
}

无符号右移 >>>

/**
 * 无符号右移 >>> 高位补0
 * 
 * >>>和>>的区别是:在执行运算时,>>>运算符的操作数高位补0,而>>运算符的操作数高位移入原来高位的值。 
 * 
 */
public static void test7() {

    /** 负数取值: 减一后按位取反 **/

    /**
     * -5 >> 2 情况
     * 11111111 11111111 11111111 11111011 -5 的二进制
     * 11111111 11111111 11111111 11111110 >> 2
     * 10000000 00000000 00000000 00000010 减1,按位取反,值为-2
     */
    System.out.println(-5 >> 2);// 结果是-2

    /**
     * -5 >>> 2 情况
     * 11111111 11111111 11111111 11111011 -5 的二进制
     * 00111111 11111111 11111111 11111110 >>> 2, 高位补0,此时为正数
     */
    System.out.println(-5 >>> 2);// 结果是1073741822
}
posted @ 2023-10-30 08:45  mingshan  阅读(9)  评论(0编辑  收藏  举报