位运算符及其用途

发布时间 2023-09-08 16:29:13作者: upupup-999

位运算符以及其的用途

1. & --------按位与运算

"&"是双目运算符双目运算符就是有两个操作数
只有当二进制对应位上都是1的时候结果才为1。

a b a&b
1 1 1
1 0 0
0 1 0
0 0 0

用途:

  1. 限制数值在某个范围内

     int number = 10;
     int res = 7 & number;
    

    在这段代码中,7 & number 是一个按位与运算。

    首先,将 7number 转换为二进制表示:

      7   : 0000 0111
    number: 0000 1010
    

    然后进行按位与运算:

         0000 0111   (7)
       & 0000 1010   (number)
       -----------------------
         0000 0010   (2)
    

    按位与运算的规则是,只有在相应的位上都是 1 时,结果才为 1;否则,结果为 0。因此,在这个例子中,只有第二位上的 1 对应的位置都是 1,其他位都为 0。所以,最终的结果 res 为 2。

    因此,res 的结果为 2。

  2. 判断奇偶数

    二进制中只有当最后一位二进制数为1的时候才表示奇数,而相反只有当最后一位二进制数为0的时候才表示偶数,所以利用“&”的特点,我们可以得到:

    • 与奇数:7&1
      7   : 0000 0111
      &  :          1
        -----------------------
            0000 0001   (1)
    
    • 与偶数:8&1
      8   : 0000 1000
      &     :       1
        -----------------------
            0000 0000   (0)
    

    代码如下:

    if((x&1) == 1)
    	printf("x是奇数\n");
    	
    else if((x&1) == 0)
    	printf("x是偶数\n");
    
    

2. ^ --------按位异或运算

“^”是双目运算符,对底层二进制串进行运算,比算术运算快得多,规则为:相同为0,不同为1。

a b a^b
1 1 0
1 0 1
0 1 1
0 0 0

性质:

假设num为任意实数

  • 0 ^ num= num :0^7

      7   : 0000 0111
      ^  :  0000 0000
        -----------------------
            0000 0111   (7)
    

    即:0与任何数进行异或,结果都是任何数

  • num ^ num = 0 :7^7

      7   : 0000 0111
      ^  :  0000 0111
        -----------------------
            0000 0000  (0)
    

    即:任何数与自身进行异或,结果都是0

  • 异或运算的交换律:a ^ b = b ^ a

    a ^ b = b ^ a
    

重点:我们可以将异或运算理解为二进制的无进位相加!也就是说,当两个数异或的时候,如果某一位同为1,则该位为0并且不向前进位。

用途:

  1. 交换两个数字的值

        public void swap(Integer a, Integer b) {
            a = a ^ b;
            b = a ^ b;//b=a ^ b ^ b 相等异或为0,0与任何数异或得任何数 即b=a
            a = a ^ b;//a=a ^ b ^ a 相等异或为0,0与任何数异或得任何数 即a=b
        }
    

    注意:在于当交换的是同一个索引时,也就是i和j相等时,会导致结果不正确。交换后最终为0

    代码如下:

        public void swap(int[] arr,int i,int j) {
            //这里实参i,j是相同的下标 即arr[i]==arr[j]
            arr[i] = arr[i] ^ arr[j];
            arr[j] = arr[i] ^ arr[j];//arr[j] =arr[i]  ^ arr[j]  ^ arr[j]  相等异或为0,0与任何数异或得任何数 即arr[j] =0
            arr[i] = arr[i] ^ arr[j];//arr[i] =arr[i]  ^ arr[j]  ^ arr[i]  相等异或为0,0与任何数异或得任何数 即arr[i] =0
    
        }
    
  2. 只出现一次的数字

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
    说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
    
        public static int findOne(int[] arr){
            //初始为0,
            int res=0;
            for (int i : arr) {
                res^=i;
            }
            return res;
        }
    

    提示:所有重复出现的数据会被抵消为0,剩下的就是只出现一次的

3. | --------按位或运算

“|”是双目运算符,
只有当二进制对应位上有一个为1,结果为1

a b a或b
1 1 1
1 0 1
0 1 1
0 0 0

用途:

  1. 对一个数据的某些位 - 置 1

    例:将 X=10100000 的低 4 位 置 1 ,用 X | 0000 1111 = 1010 1111 即可得到

      X  : 1010 0000  (160)
      |  : 0000 1111  (15)
        -----------------------
            1010 1111   (175)
    
  2. 强行变成最接近的偶数 即:把二进制最末位变成 0

    对这个数 or 1 之后会使最后以为保持不变(奇数),或者加1(偶数),目的就是将这个数变为奇数,之后之后再减一就可以了

      7   : 0000 0111
      ^  :  0000 0001
        -----------------------
            0000 0111   (7)
    

4. ~ -------求反运算符

“~”为单目运算符(只有一个操作数),具有右结合性(从右向左执行计算),

a ~a
0 1
1 0

5. << -----左移运算符

“<<”是双目运算符,将二进制位进行左移操作,
左移n位就是乘以2的n次方。

“<<”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0。

6.>> --------右移运算符
“>>”是双目运算符,将二进制位进行右移操作,
右移n位就是除以2的n次方。

“>>”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。同时注意,>>运算符是用符号位来填充高位的。