Java中的位运算及简单的算法应用介绍

众所周知,计算机底层是二进制。而java作为一门计算机编程语言,也对二进制的位运算提供了完整的支持。

在java中,int是32位的,也就是说可以用来实现32位的位运算。方便起见,我们一般用16进制对它赋值,比如: 0011表示成16进制是 0x3, 110111表示成16进制是 0x37。

那么什么是位运算呢?位运算是将数据看做二进制,进行位级别的操作。主要有移位运算和逻辑运算

移位运算:

  • 左移:操作符为<<,向左移动,右边的低位补0,左边高位舍弃,将二进制看做整数,左移1位就相当于乘以2。
  • 无符号右移:操作符为>>>,向右移动,右边的舍弃掉,左边补0。
  • 有符号右移:操作符为>>,向右移动,右边的舍弃掉,左边补的值取决于原来最高位,原来是1就补1,原来是0就补0,将二进制看做整数,右移1位相当于除以2。

10进制转二进制的时候,因为二进制数一般分8位、 16位、32位以及64位 表示一个十进制数,所以在转换过程中,最高位会补零。

在计算机中负数采用二进制的补码表示,10进制转为二进制得到的是源码,将源码按位取反得到的是反码,反码加1得到补码

二进制的最高位是符号位,0表示正,1表示负。

例如:

        int a = 4; //100
        a = a >> 2; //001,
        System.out.println("4>>2运算的结果是 :" + a);//变为1
        a = 4; //100
        a = a << 3; //100000,
        System.out.println("4<<3运算的结果是 :" + a);//变为32

        System.out.println("16>>2运算的结果是 :" + ((16) >> 2));//变为4
        System.out.println("-16>>2运算的结果是 :" + ((-16) >> 2));//变为-4
        System.out.println("16>>>2运算的结果是 :" + ((16) >>> 2));//变为4
        System.out.println("-16>>>2运算的结果是 :" + ((-16) >>> 2));//变为大的整数,看是多少位的

得到结果

可见正数做>>>运算的时候和>>是一样的。区别在于负数运算.

逻辑运算有:

  • 按位与 &:两位都为1才为1
  • 按位或 |:只要有一位为1,就为1
  • 按位取反 ~: 1变为0,0变为1
  • 按位异或 ^ :相异为真,相同为假

例如:

int a = ...; 
a = a & 0x1 // 返回0或1,就是a最右边一位的值。
a = a | 0x1 //不管a原来最右边一位是什么,都将设为1

我们来看几个简单的应用场景:

场景一:判断奇偶

分析:奇数都不是2的整数倍,转换成二进制后最低位必然为1,偶数则相反。利用这个特性我们可以很容易的通过位运算判断一个整数的奇偶性。

看代码:

    int i = 1;// 二进制存储方式为00000000000000000000000000000001
    int j = 5;// 二进制存储方式为00000000000000000000000000000101
    int k = 6;// 二进制存储方式为00000000000000000000000000000110
    if ((i & j) == 1) {
      System.out.println("j的最低位为1,为奇数");
    }
    if ((i & k) == 0) {
      System.out.println("k的最低位为0,为偶数");
    }

场景二:判断一个正整数是不是2的整数次幂

分析:我们先来看一下常见的2的整数次幂的数:2、4、8、16,转化成二进制依次为:10、100、1000、10000,发现规律了没有?那就是除了首位是1,其他全是0。恰巧这些数减去1后等于他们依次按位取反的结果,比如8-1=7,二进制是111,可以通过8的二进制1000按位取反得到。而8&7=0,提取一下规律就是:

(n&(n-1))==0

符合这个规律的n就是2的整数次幂了。

原文地址:https://www.cnblogs.com/grasp/p/11486000.html