首页 > 编程笔记

Java位运算符(位逻辑运算符+位移运算符)

Java 语言中的位运算符分为两大类:位逻辑运算符和位移运算符。

位运算符如下表所示:

表 1 位运算符
运算符 含义 举例
& a & b
| a | b
~ 取反 ~a
^ 异或 a ^ b
<< 左移位 a << 2
>> 右移位 b >> 4
>>> 无符号右移位 x >>> 2

下面分别对位逻辑运算符和位移运算符予以介绍。

位逻辑运算符

位逻辑运算符包括 &、|、^ 和 ~,其运算结果如下表所示。

表 2 位逻辑运算符的运算结果
A B A & B A | B A^B ~A
0 0 0 0 0 1
1 0 0 1 1 0
0 1 0 1 1 1
1 1 1 1 0 0

参照上表来看一下这 4 个运算符的实际运算过程。

1)位逻辑与

实际上是将操作数转换成二进制表示方式,然后将两个二进制操作数对象从低位(最右边)到高位对齐,每位求与。若两个操作数对象同一位都为 1,则结果对应位为 1;否则结果对应位为 0。

例如,12 和 8经过位逻辑与运算后得到的结果是 8。
  0000 0000 0000 1100  (十进制数12的原码表示)
& 0000 0000 0000 1000  (十进制数8的原码表示)
  0000 0000 0000 1000  (十进制数8的原码表示)

2) 位逻辑或

实际上是将操作数转换成二进制表示方式,然后将两个二进制操作数对象从低位(最右边)到高位对齐,每位求或。若两个操作数对象同一位都为 0,则结果对应位为 0;否则结果对应位为 1。

例如,4 和 8 经过位逻辑或运算后的结果是 12:
  0000 0000 0000 0100  (十进制数4的原码表示)
| 0000 0000 0000 1000  (十进制数8的原码表示)
  0000 0000 0000 1100  (十进制数12的原码表示)

3) 位逻辑异或

实际上是将操作数转换成二进制表示方式,然后将两个二进制操作数对象从低位(最右边)到高位对齐,每位求异或。若两个操作数对象同一位不同,则结果对应位为 1;否则结果对应位为 0。

例如,31 和 22 经过位逻辑异或运算后得到的结果是 9:
  0000 0000 0001 1111  (十进制数31的原码表示)
^ 0000 0000 0001 0110  (十进制数22的原码表示)
  0000 0000 0000 1001  (十进制数9的原码表示)

4) 位逻辑取反

实际上是将操作数转换成二进制表示方式,然后将各位二进制位由 1 变为 0,由 0 变为 1。

例如,123 经过位逻辑取反运算后得到的结果是 -124:
~  0000 0000 0111 1011 (十进制数123的原码表示)
   1111 1111 1000 0100 (十进制数−124的原码表示)

&、| 和 ^ 也可以用于逻辑运算,运算结果如下表所示。

表 3 位逻辑运算符的运算结果
A B A & B A | B A ^ B
true true true true false
true false false true true
false true false true true
false false false false false
【实例】
public class BitwiseAnd {
    public static void main(String[] args) {
        int a = 12; // 二进制: 1100
        int b = 7;  // 二进制: 0111
        int result = a & b; // 按位与的结果为 0100,即4
       
        System.out.println("按位与的结果: " + result);
    }
}
运行结果为:

按位与的结果: 4

实例中,我们对整数 a 和 b 进行按位与操作,比较每一位,只有当两位都为 1 时,结果位才为 1。

位移运算符

位移运算符有 3 个,分别是左移运算符 <<、右移运算符 >> 和无符号右移运算符 >>>。

在介绍位移运算符前,先来学习下什么是二进制数。

所谓二进制数,是指用 0 和 1 来表示的数。例如,十进制数 42 的二进制表示形式为 101010。那么,十进制数如何转换为二进制数呢?以十进制数 42 为例,将十进制数 42 转换成二进制数的过程如下图所示。


图 1 将十进制数42转换成二进制数

因为计算机内部表示数的字节单位是定长的,例如 8 位、16 位或 32 位,所以当二进制数的位数不够时,须在高位补零。十进制数 42 的二进制表示形式为 101010,如果计算机的字长是 8 位,那么 101010 的规范写法为 0010 1010。

如果把十进制数 −42 转换成二进制数,过程又是怎样的呢?先将对应的正整数转换成二进制数,再对二进制数取反,最后对结果加一,具体的转换过程如下图所示。


图 2 将十进制数-42转换成二进制数

综上所述,十进制数 −42 的二进制表示形式为 1101 0110。

掌握“什么是二进制数”和“十进制数是如何转换为二进制数的”这两个内容后,再来学习下左移、右移和无符号右移这3种运算。

1) 左移运算

左移运算是将一个二进制操作数对象按指定的位数向左移,左边(高位端)溢出的位被丢弃,右边(低位端)的空位用 0 补充。左移 n 位相当于乘以 2n,如下图所示。


图 3 左移运算

例如,short 型整数 9115 的二进制形式是 0010 0011 1001 1011,左移一位变成 18230,左移两位变成 36460,如下图所示。


图 4 左移运算过程

2) 右移运算

右移运算是将一个二进制数按指定的位数向右移动,右边(低位端)溢出的位被丢弃,左边(高位端)用符号位补充,正数的符号位为 0,负数的符号位为 1。右移 n 位相当于除以 2n,如下图所示。


图 5 右移运算

例如,short 型整数 9115 的二进制形式是 0010 0011 1001 1011,右移一位变成 4557,右移两位变成 2278,运算过程如下图所示。


图 6 正数右移运算过程

short 型整数 -32766 的二进制形式是 0010 0011 1001 1011,右移一位变成 -16383,右移两位变成 -8192,运算过程如下图所示。


图 7 负数右移运算过程

3) 无符号右移运算

无符号右移运算是将一个二进制的数按指定的位数向右移动,右边(低位端)溢出的位被丢弃,左边(高位端)一律用 0 填充,相当于除以 2 的幂。

例如 int 型整数 -32766 的二进制形式是 1111 1111 1111 1111 1000 0000 0000 0010,右移一位变成 2147467265,右移两位变成 1073733632,运算过程如下图所示。


图 8 无符号右移运算过程

【实例】使用位移运算符对变量进行位移运算
public class BitwiseShiftExample {
    public static void main(String[] args) {
        int number = 10; // 二进制表示为 1010
        int shift = 2; // 将数字左移2位

        // 左移操作后,二进制表示为 101000,即 40
        int result = number << shift;

        System.out.println("原始数字: " + number);
        System.out.println("左移 " + shift + " 位后的结果: " + result);
    }
}
运行结果为:

原始数字: 10
左移 2 位后的结果: 40

推荐阅读