位运算详解之与或非的巧妙运用
位运算详解之与或非&|~的巧妙运用
- 一、位运算基础概念
- 1.1 位运算的定义与本质
- 1.2 与(&)运算
- 1.3 或(|)运算
- 1.4 非(~)运算
- 二、与运算的巧妙运用
- 2.1 提取二进制位
- 2.2 判断奇偶性
- 2.3 关闭某些位
- 三、或运算的巧妙运用
- 3.1 设置二进制位
- 3.2 合并二进制数
- 3.3 初始化变量
- 四、非运算的巧妙运用
- 4.1 生成反码
- 4.2 切换状态
- 4.3 按位取反实现特定逻辑
- 五、运用实例
- 5.1 状态压缩
- 5.2 数据加密与校验
与(&)、或(|)、非(~)作为最基本的位运算操作,通过巧妙组合与运用,能解决许多复杂的算法问题、实现高效的数据处理,甚至在底层系统设计中发挥关键作用。
一、位运算基础概念
1.1 位运算的定义与本质
位运算直接对二进制位进行操作,计算机中的数据以二进制形式存储,位运算就是对这些二进制位进行逻辑或算术操作。与、或、非是最基础的位运算,它们基于二进制位的逻辑关系进行计算,是理解和使用其他复杂位运算(如异或、位移等)的基础。
1.2 与(&)运算
与运算的规则是:当两个二进制位都为1时,结果为1;否则结果为0。可以用逻辑表达式表示为:0 & 0 = 0
,0 & 1 = 0
,1 & 0 = 0
,1 & 1 = 1
。例如,对于十进制数5
(二进制为0101
)和3
(二进制为0011
),它们进行与运算:
0101
& 0011
------0001
结果为1
(二进制0001
)。从逻辑意义上讲,与运算可以用于提取二进制数中某些特定位置的位,或者判断某些位是否同时为1。
1.3 或(|)运算
或运算的规则是:只要两个二进制位中有一个为1,结果就为1;只有当两个二进制位都为0时,结果才为0。逻辑表达式为:0 | 0 = 0
,0 | 1 = 1
,1 | 0 = 1
,1 | 1 = 1
。例如,5
(0101
)和3
(0011
)进行或运算:
0101
| 0011
------0111
结果为7
(二进制0111
)。或运算常用于将二进制数中某些位置的位设置为1,或者合并多个二进制数的某些特征位。
1.4 非(~)运算
非运算也称为取反运算,它将二进制位中的0变为1,1变为0。例如,对于十进制数5
(二进制0101
),进行非运算:
~ 0101
------1010
在计算机中,非运算的结果会根据数据类型的范围进行处理,通常会涉及到补码等概念。非运算常用于生成与原二进制数相反的位模式,或者在一些算法中用于改变位的状态。
二、与运算的巧妙运用
2.1 提取二进制位
在处理二进制数据时,有时需要提取其中某些特定位置的位。例如,有一个8位二进制数10101101
,想要提取其低4位,可以将该数与00001111
进行与运算:
10101101
& 00001111
----------00001101
这样就成功提取出了低4位的数据。在实际编程中,这种操作可用于处理网络协议中的数据包头字段、文件格式中的特定标志位等。
2.2 判断奇偶性
判断一个整数的奇偶性是与运算的一个简单而巧妙的应用。对于一个整数n
,如果n & 1
的结果为1
,则n
为奇数;如果结果为0
,则n
为偶数。这是因为奇数的二进制表示的最低位为1,偶数的二进制表示的最低位为0,通过与1
进行与运算,可以快速判断最低位的值。例如:
public class AndOperationExample {public static boolean isOdd(int n) {return (n & 1) == 1;}public static void main(String[] args) {System.out.println(isOdd(5)); // 输出 trueSystem.out.println(isOdd(6)); // 输出 false}
}
2.3 关闭某些位
当需要将二进制数中某些特定位置的位设置为0时,可以使用与运算。假设有一个二进制数11111111
,想要将其第3位和第5位关闭(设置为0),可以将该数与11010111
进行与运算:
11111111
& 11010111
----------11010111
这种操作在权限控制、状态标志位管理等场景中经常用到,比如关闭某些用户权限对应的标志位。
三、或运算的巧妙运用
3.1 设置二进制位
与关闭位相反,或运算可以用于将二进制数中某些特定位置的位设置为1。例如,有一个二进制数00000000
,想要将其第2位和第4位设置为1,可以将该数与00010100
进行或运算:
00000000
| 00010100
----------00010100
在图形处理中,设置像素点的某些颜色通道值就可以利用或运算实现。
3.2 合并二进制数
或运算能够将两个二进制数的特征位进行合并。假设有两个二进制数,一个表示用户的基本权限00100100
,另一个表示用户的临时权限01001000
,将它们进行或运算可以得到用户的总权限:
00100100
| 01001000
----------01101100
这种方式在用户权限管理、状态标识合并等场景中非常实用。
3.3 初始化变量
在一些情况下,需要将变量的某些位初始化为特定的值。使用或运算可以方便地实现这一操作。例如,将一个整数变量的低8位初始化为1
,可以将该变量与0000000011111111
进行或运算:
public class OrOperationExample {public static void main(String[] args) {int num = 0;num = num | 0xff;System.out.println(Integer.toBinaryString(num)); // 输出 11111111}
}
四、非运算的巧妙运用
4.1 生成反码
非运算最直接的应用就是生成一个数的反码。在计算机中,补码运算常用于表示负数,而反码是计算补码的中间步骤。例如,对于正数5
(二进制00000101
),其反码为11111010
。在一些加密算法、数据校验算法中,会利用反码进行数据的变换和处理。
4.2 切换状态
非运算可以用于切换二进制位的状态,即0变为1,1变为0。在状态机的实现中,当需要切换某个状态标志位时,可以使用非运算。比如,有一个标志位flag
,用于表示某个功能是否开启,通过flag = ~flag
可以实现功能的开启与关闭切换。
public class NotOperationExample {public static void main(String[] args) {boolean flag = true;// 使用位运算模拟状态切换(这里用int类型的最低位模拟)int flagBit = 1;flagBit = ~flagBit;System.out.println((flagBit & 1) == 1); // 输出 false}
}
4.3 按位取反实现特定逻辑
在一些算法中,通过对某些二进制位进行取反操作,可以实现特定的逻辑判断或数据处理。例如,在判断一个数是否为2的幂次方时,可以利用(n & (n - 1)) == 0
这个特性,其中n - 1
可以通过对n
进行一系列位运算得到,非运算在其中起到了关键作用 。
五、运用实例
5.1 状态压缩
在一些需要处理多个状态的场景中,可以使用位运算进行状态压缩。例如,有8个开关,每个开关有开和关两种状态,使用一个字节(8位二进制数)就可以表示这8个开关的所有状态组合。通过与、或、非运算,可以方便地设置、查询和修改每个开关的状态。
public class StateCompressionExample {public static void main(String[] args) {int state = 0; // 初始状态,所有开关关闭// 打开第3个和第5个开关state = state | (1 << 2) | (1 << 4);// 判断第3个开关是否打开boolean isOn = (state & (1 << 2)) != 0;System.out.println(isOn); // 输出 true// 关闭第5个开关state = state & ~(1 << 4);}
}
5.2 数据加密与校验
在简单的数据加密和校验场景中,位运算也能发挥作用。例如,通过将数据与一个密钥进行异或运算(异或运算可由与、或、非运算组合实现)进行加密,接收方再用相同的密钥进行异或运算解密。在数据校验中,利用位运算生成校验码,验证数据在传输过程中是否发生错误。
That’s all, thanks for reading!
觉得有用就点个赞
、收进收藏
夹吧!关注
我,获取更多干货~