位运算
由于在阅读java的源码时,发现其中用了大量的位运算,所以就将位运算作为第一篇文章进行发布了
位运算的简介
1. 什么是位运算
现代计算机中,几乎都是二进制计算机,所有的数据都以二进制的形式存储在设备中。位运算就是直接对存储在内存中的数据的二进制位进行操作。
在计算机中,每一个二进制位称为1个bit,单位简写做 b。通常8个bit为一个单位,称为 字节(byte),单位简写作 B。
一个字节不一定是8位,由硬件决定。但现在通用的标准中,一个字节等于8位
常用的位运算
在 n 位二进制数中,我们一般称最低位为第0 位,最高位为n − 1,从右向左由低到高进行排列
与 | 或 | 非 | 异或 | 左移 | 右移 | |
---|---|---|---|---|---|---|
运算符 | & | ~ | ^ | << | ||
1. 按位与
在 逻辑与 运算中,参与运算的两个布尔值只有 0 和 1 两种取值,只有当两个布尔值都为1时,结果才得1,其余只要有一个值为0,结果就为0,类似乘的关系。逻辑与 的符号为 &&。
2. 按位或
在 逻辑或 运算中,参与运算的两个布尔值只有 0 和 1 两种取值,只有当两个布尔值都为0时,结果才得0,其余只要有一个值为1,结果就为1,类似加的关系(不进位),逻辑或的符号为 ||。
3. 按位取反
在 逻辑非 运算中,布尔值只有 0 和 1 两种取值,当布尔值为0时结果为1,当布尔值为1时结果为0,逻辑非的符号为 !。
4. 按位异或
在 逻辑异或 运算 中,参与运算的两个布尔值只有 0 和 1 两种取值,只有当两个布尔值不同时,结果才得1,其余结果为0,类似不等于的关系,逻辑异或在数学上一般用符号 ⊕ 表示。
在编程语言中很少有 逻辑异或 的符号,运算中一般用不等于(!=)替代,
前提是参与运算的两个都是布尔值。
当按位异或运算符应用于一个数两次时,它会将该数的每一位与自身进行异或运算。
由于异或运算的性质,当两个二进制数的对应位相同时,异或的结果为0,而当对应位不同时,
异或的结果为1。因此,当一个数与自身进行两次异或运算时,对应位相同的位将得到0,
而对应位不同的位将得到1。这样,每个位都会返回到原始值。利用这个特性可以将因进行
了按位异或而被改变的数据还原。
eg
00100
^ 11101=11001
11001
^ 11101=00100
5. 左移运算
左移运算是一种位运算操作,用于将一个数的所有位向左移动指定的位数。在左移运算中,数的每一位都向左移动,并且在右侧填充零。左移运算可以看作是对二进制数进行乘以2的操作。最左边的 n 个二进制位将因被移出边界而丢弃,移动后最右边空出来的二进制位补0。在没有发生 溢出 和 环绕 的情况下,n 左移一位后的值相当于 2 n
6. 右移运算
右移运算是一种位运算操作,用于将一个数的所有位向右移动指定的位数。在右移运算中,数的每一位都向右移动,并且在左侧进行填充操作,根据符号位的情况可能填充符号位或者零。右移运算可以看作是对二进制数进行除以2的操作
右移运算有两种形式:逻辑右移和算术右移。
-
逻辑右移(Logical Right Shift):对无符号数进行右移运算,右侧用零进行填充。无论符号位是0还是1,都在左侧填充零。
-
算术右移(Arithmetic Right Shift):对有符号数进行右移运算,右侧用符号位进行填充。当符号位为0时,在左侧填充零;当符号位为1时,在左侧填充1。
例如,对于一个二进制数10110,进行右移运算1位,逻辑右移和算术右移的结果如下:
逻辑右移:10110 >> 1 = 01011
算术右移:10110 >> 1 = 11011