前言
在了解 Java 位运算前,需要先了解如下内容:
机器数、真值
计算机和真实生活中不同,一个数在计算机中只能以二进制 (0 或 1) 的方式表示,现实生活中主要以十进制表示,在二进制的表示中,最高位是符号位,最高为如果是 0 , 则表示该数的十进制表示为正数,如果最高位是 1, 则该数为负数。
以十进制 3 为例,改为 8 位的二进制,则是 [0000 0011], 如果是 -3 转换为 8 位二进制,则是 [1000 0011]。在这里 [0000 0011] 与 3 表示的意思相同,不过 [0000 0011] 是机器数,3 为真值。
原码、反码、补码
一个数,取绝对值大小转换为二进制,称其为原码。正常情况下,对计算机的两个数进行加法运算,由于不知道符号,所以对其取补码后进行运算,正数的补码是其本身,负数的补码是对其正数取反加 1。
原码
正数的原码是本身。负数的原码是其正数的原码最高位改为 1
示例:1, -1 转换为 8 位的二进制原码
1 的原码 = [0000 0001]
-1 的原码 = [1000 0001]
反码
正数的反码是本身。负数的反码是其最高位不变,其他位取反
示例:1, -1 转换为 8 位的二进制反码
1 的反码 = [0000 0001]
-1 的反码 = [1111 1110]
补码
正数的补码是本身。负数的补码是最高位不变,其他位取反,最后位 + 1 (即 反码 + 1)
示例:1, -1 转换为 8 位的二进制补码
1 的补码 = [0000 0001]
-1 的补码 = [1111 1111]
已知一个数的补码求其原码,就是对补码再求补码。
在 Java 中所有数据都是以补码的形式存在的。(可通过以下代码验证)
举例来说 int 类型占 4 个字节,每个字节长度是 8 位,共 32 位。取整数 1 来说 二进制的标示为 [0000 0000 0000 0000 0000 0000 0000 0001]。
|
|
Java 位运算
位逻辑运算符
位逻辑运算符对操作数的每一位进行逻辑运算,并将结果返回。
&
(按位与运算符)
将操作数的每一位进行逻辑与运算,即只有当两个操作数的对应位都为 1 时,结果才为 1。
例: 1, 2 进行与运算:
计算过程:
1: [0000 0001]
2: [0000 0010]
&: [0000 0000] = 0
|
|
|
(按位或运算符)
将操作数的每一位进行逻辑或运算,即只要有一个操作数的对应位为 1,结果就为 1。
例:1, 2 进行或运算
计算过程:
1: [0000 0001]
2: [0000 0010]
|: [0000 0011] = 3
|
|
~
(按位非运算符)
将操作数的每一位取反,即 0 变成 1,1 变成 0。(此时得到的是补码,最终结果是补码的原码)
例: ~0 = -1
计算过程:
0: [0000 0000]
~: [1111 1111] —(转换为原码)—> [1000 0001] = -1
|
|
^
(按位异或运算符)
将操作数的每一位进行逻辑异或运算,即只有当两个操作数的对应位不同时,结果才为 1。
例: 3, 5 进行异或运算
计算过程:
3: [0000 0011]
5: [0000 0101]
^: [0000 0110] = 6
|
|
移位运算符
移位运算符将操作数的每一位向左或向右移动指定的位数。(移除的低位被舍弃)
<<
(左移运算符)
将操作数的每一位向左移动指定的位数,并在低位补零。
x << y
,计算结果相当于:x 乘以 2 的 y 次幂 ( $x * 2^y$ )
示例 1
计算:5 << 2
5: [0000 0101] (有效值 101) << 2
= [0001 0100] = 20
相当于:$5 * (2^2) = 5 * 4 = 20$
示例 2
计算:2147483647 << 1
2147483647 的二进制:
0111 1111 1111 1111 1111 1111 1111 1111
2147483647 << 1:
1111 1111 1111 1111 1111 1111 1111 1110 (第一位符号位为 1, 负数,该值为补码)
依据补码求原码:(除符号位取反 + 1):
(除符号位取反):
1000 0000 0000 0000 0000 0000 0000 0001
(+1):
最后结果的二进制:
1000 0000 0000 0000 0000 0000 0000 0010 = -2
>>
(有符号右移运算符)
>>
将操作数的每一位向右移动指定的位数,并在高位根据操作数的符号位进行扩展。
x >> y
,计算结果相当于: x 除以 2 的 y 次幂 ( $x / 2 ^ y$ )
示例:5 >> 2
计算过程:
5: [0000 0101] >> 2
= [0000 001] = 1
相当于:$5 / (2^2) = 5 / 4 = 1$
>>>
(无符号右移运算符)
将操作数的每一位向右移动指定的位数,并在高位都补零。(移除的低位被舍弃)
正数的 >>>
和 >>
无区别,负数则会变成正数。
感谢您的耐心阅读!来选个表情,或者留个评论吧!