Java位运算浮以及移位操作符的运用

学习了Java的数据类型和变量,今天我们将学习Java中的运算符,Java的运算符相关操作同C语言一样,这里我们主要讲解一些位运算符和移位操作符!!!

学前须知:

任何一个整数,在内存中都是按照二进制的补码存储的,原码的最高位是符号位,整数为0,负数为1;

对于一个整数来说:其原码,反码,补码都是一样的;

对于一个负数来说:其原码除符号位外按位取反为其反码,其反码+1为其补码

再说一遍,记住:所有整数都是按照补码形式存储在内存中的,若为正数补码=原码,若为负数则需要计算,通过补码求出反码再求出原码最后转换成整数

 一·位运算符

Java 中数据存储的最小单位是字节,而数据操作的最小单位是比特位 . 字节是最小的存储单位,每个字节是由 8 个二 进制比特位组成的,多个字节组合在一起可以表示各种不同的数据。
位运算符主要有四个 : & | ~ ^ ,除 ~ 是一元运算符外,其余都是二元运算符。
位操作表示 按二进制位运算 . 计算机中都是使用二进制来表示数据的 (01 构成的序列 ), 按位运算就是在按照二进制位 的每一位依次进行计算.
下面的示例均只给出补码(即在内存中的状态,若需要计算出其原码请读者自行计算)

1.1 按位与 &

如果两个二进制位都是 1, 则结果为 1, 否则结果为 0. (作用:寻找二进制中的1)

 1.2按位或(|) 

如果两个二进制位都是 0, 则结果为 0, 否则结果为 1. (作用:寻找二进制中的0)

 1.3按位取反 ~

如果该位为 0 则转为 1, 如果该位为 1 则转为 0(单目操作符)

1.4 按位异或 ^

如果两个数字的二进制位相同 , 则结果为 0, 相异则结果为 1. (作用:找不同) 

 二·移位操作符

移位运算符有三个 : << >> >>> ,都是二元运算符,且都是按照二进制比特位来运算的

2.1 左移操作符 <<

左移 << : 最左侧位不要了 , 最右侧补 0.

 2.2 右移操作符 >>

右移 >> : 最右侧位不要了 , 最左侧补符号位 ( 正数补 0, 负数补 1)

 2.3 无符号右移 >>>

无符号右移 >>>: 最右侧位不要了 , 最左侧补 0.

总结:

1. 左移 1 位, 相当于原数字 * 2. 左移 N 位, 相当于原数字 * 2 的N次方.
2. 右移 1 位, 相当于原数字 / 2. 右移 N 位, 相当于原数字 / 2 的N次方.
3. 由于计算机计算移位效率高于计算乘除, 当某个代码正好乘除 2 的N次方的时候可以用移位运算代替.
4. 移动负数位或者移位位数过大都没有意义.

 

根据上述总结,下次进行移位操作时,可以直接计算了!!!




学习完相关知识,我们一起来看两个题:

1.求一个整数,在内存当中存储时,二进制1的个数

法一:

思想:用这个数&1,若等于1则找到一个1,没进行一次&运算,让这个数右移,故32位需要右移31次

 public static void main(String[] args) {
        //输入一个数
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        //计算1的个数
        int count = 0;
        for (int i = 0; i < 32; i++) {
            if((num&1) == 1){
                count++;
            }
            num = num>>1;
        }
        System.out.println(count);

    }

 

法二:

思想:在法一的基础上进行优化,若某一次这个数进行完&运算之后已经等于0了,就不需要再继续查找了

  public static void main(String[] args) {
        //输入一个数
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        //计算1的个数
        int count = 0;
        while(num != 0){
           if((num&1) == 1){
               count++;
           }
           num = num>>>1;
       }
        System.out.println(count);

    }

 

法三:

思想:这是一个算法层面的方法,比较难想,每次用这个数num&(num-1),若不等于0,则count++,直至num=0时查找结束

public static void main(String[] args) {
        //输入一个数
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        //计算1的个数
        int count = 0;
        while(num != 0){
            count++;
            num = num&(num-1);
        }
        System.out.println(count);

    }

 

 2.获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列

思想:一个数的二进制序列,求奇数序列:从最右边第一个数开始,右移31位可移到第一个数,设初值i=31,然后&1进行判断,每进行一次&操作,i=i-2,直到i=1;求偶数序列:从右边第一个数开始,右移30位可以移到第二个数,设初值i=0,然后&1进行判断,每进行一次&操作,i=i-2,直到i=0。

 public static void main(String[] args) {
        //输入一个数
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        //假设输入的是7
        //7的二进制序列为:00000000000000000000000000000111
        //奇数序列:0000000000000001
        //偶数序列:0000000000000011
        for (int i = 31; i >= 1; i -= 2) {
            System.out.print(((num >> i) & 1) + " ");
        }
        System.out.println();
        for (int i = 30; i >= 0; i -= 2) {
            System.out.print(((num >> i) & 1) + " ");
        }

    }

 




位运算及移位运算符的讲解到这里结束啦,希望大家可以好好消化这两个题目,对我们理解帮助非常大,同时这也是《剑指offer》上面的题目,感谢支持!!!

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值