0
点赞
收藏
分享

微信扫一扫

位运算--位运算的基本用法(基础)

转角一扇门 2022-03-12 阅读 65

位运算的基本概念

在计算机中的数在内存中都是以二进制的形式存储的,位运算可以直接对内存中的二进制进行操作,相比在代码中直接使用(+、-、*、/)运算符,合理使用位运算能大大的提高程序的性能。
这里以整型为例,在计算机中,整型是以32为二进制存储的.
整数的最高位为符号位,正数为0,负数为1
10000000000000000000000000000000 <= int <=01111111111111111111111111111111
所以int的范围为:-231<= int <=231-1

负数化成十进制为:最高位不变,其余取反+1

正数直接二进制化成十进制就可以了,正负数转换见(~)取反运算

位操作符

与运算(&)

与运算两个为都是1 的结果为1,否则为0

注意:负数按补码的形式按位与运算

用与运算判断奇偶,只要根据末尾是0还是1,为0就是偶数,为1就是奇数。就可以用 (x & 1 == 0)来判断是不是偶数。
代码:

//打印偶数
public class code01 {
    public static void main(String[] args) {
        for (int i=0;i<=10;i++){
            if((i & 1)==0){
                System.out.print(i+" ");
            }
        }
    }
}

在这里插入图片描述

或运算(|)

参与运算的两个对象只要有一个为1,其值就为1

1)常用来对一个数据的某些位设置为1

比如将数 X=1010 1110 的低4位设置为1,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位或运算(X|Y=1010 1111)即可得到。

异或运算 (^)

相同为1,相宜为0

异或的几条性质:

  • 交换律
  • 结合律 ( a ^ b) ^ c == a ^ (b ^ c)
  • 对于任何数a,都有a ^ a = 0 , a ^ 0 = a
  • 自反性:a ^ b ^ b = a ^ 0 = a

使用异或解决问题

使用异或交换:

 		c = a ^ b;
        b = c ^ b;
        a = c ^ a;

只出现一次的数字:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

示例:

代码实现:

class Solution {
    public int singleNumber(int[] nums){
        int a=0;
        for(int i=0;i<nums.length;i++)
            a=a^nums[i];
        return a;
  }   
}

取反运算符(~)

对一个二进制数按位取反,即将0变1,1变0。

取反加1,将正数变成负数,负数变成整数

public static int reversal(int a){
		return ~ a + 1;
}

正数取反加1,正好变成其对应的负数(补码表示),负数取反加1,则变成其源码,即正数。

移位运算(<< >>)

左移(<<)

各二进制位全部左移若干位,高位丢弃,低位补零。

注意:左移符号不牵扯符号位的变换,最高位直接丢弃
通过左移符号打印整数的32位二进制:
代码展示:

public class Test {
    public static void main(String[] args) {
        //打印一个整数的32位二进制
        print(5);
        //整数最大值
        int a=Integer.MAX_VALUE;
        //最小值
        int b=Integer.MIN_VALUE;
        print(a);
        print(b);
    }
    public static void print(int n){
        for(int i=31;i>=0;i--){
            System.out.print((n & (1<<i)) ==0 ? 0 : 1);
        }
        System.out.println();
    }
}

在这里插入图片描述

右移(>>)

各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)
注意:(>>)是带符号位移 ;(>>)是不带符号位移

常见位运算问题

移位操作进行高低位交换

给定一个16位的无符号整数,将其高8位与低8位进行交换,求出交换的值

		a = (a >> 8) | (a << 8);

位操作实现乘除法

	int a = 2;
	a >> 1 =1
	a << 1 =4;

位操作交换两数

位操作交换两数可以不需要第三个临时变量,虽然普通操作也可以做到,但是没有其效率高

public static void swap(int a,int b){//普通方法不需要零时变量
		a = a+b;
		b = a-b;
		a = a-b;
}
public static void swap(int a,int b){//普通方法使用临时变量
		int c = a;
		a = b;
		b = c;
}
public static void swap(int a,int b){//使用异或,不需要临时变量
		a = a ^ b;  //a ^= b ---> a = (a^b);
		b = b ^ a;  //b ^= a ---> b = b^(a^b) ---> b = (b^b)^a = a
		a = a ^ b;  //a ^= b ---> a = (a^b)^a = (a^a)^b = b
}

位操作求绝对值

整数的绝对值是其本身,负数的绝对值正好可以对其进行取反加一求得,即我们首先判断其符号位(整数右移 31 位得到 0,负数右移 31 位得到 -1,即 0xffffffff),然后根据符号进行相应的操作。

public static int abs(int a) {
  	int i = a >> 31;
  	return i == 0 ? a : (~a + 1);
}

更多位运算的操作可以深入了解,掌握好位运算大大提高代码的运行效率,是代码更简洁

举报

相关推荐

0 条评论