Java位运算符

1.位与运算符 &
运算规则:真真为真,其余都是假。 相应的每一位都是1则为1,否则为0。
对于二进制位:
1 & 1 = 1
1 & 0 = 0
0 & 0 = 0
实例:
7 和 12 的二进制只有在第三位都是1,所以得出结果为4。

 

 

总结:位与运算可以获取两个数对应位相同部分,任意数字与0位与都为0,与-1位与结果为本身。

2.位或运算符 |
运算规则:假假为假,其余都是真。相应的每一位都是0则为0,否则为1。
对于二进制位:
1 | 1 = 1
1 | 0 = 1
0 | 0 = 0
实例:
7 和 12 做位或运算,只要两个数的位中存在1,都会得到1,所以最终结果是后4位都是1,得到15。

 

 

总结:位或运算可以保留两个二进制的所有1。负数的负号也会保留下来,因为位运算在计算时,符号位也会参与计算,所以如果与负数做位或操作,那么结果为负数。任意数与0位或,结果为本身;与 -1 位或,结果为 -1。

3.位非运算符 ~
运算规则:对二进制位的每一位都取反,即 1 取反为 0,0 取反为 1。
实例:

 

 

 

由上图可知:反转0的每一位, 取反结果为 -1。
总结:取反运算将每一位都反转,正数取反得到负数,负数取反得到正数。用取反运算可以计算出相反数,取反后 +1即为相反数,论证过程在下述实例求相反数中。

4.位异或运算符 ^
运算规则:真真为假,假假为真,真假为真。相应的每一位不同为1,相同则为0。
1 ^ 1 = 0
0 ^ 0 = 0
1 ^ 0 = 1
实例:
还是 7 和 12,计算示意图如下,不同的位将得到1,所以结果为11。

 

 

总结:位异或可以保留两个数的不同部分且满足以下3条:
1.交换律,a ^ b = b ^ a,多个变量亦如此,a ^ b ^ c = b ^ c ^ a。
2.任何两个相同数字进行异或,结果为0。
3.对于一个二进制来说,这个位上的数与另一个二进制位上的0异或,运算结果是这个位上的数不变;如果是与二进制位上的1异或,那么结果这个位上的数为相反数,即1 -> 0, 0 -> 1。 所以一个数异或0,结果为本身,一个数异或 -1,结果为相反数。

5.左移运算符 <<
说明:移位运算符只作用于整形变量,分为两类,第一类是long类型,long类型长度为 64 字节;第二类为 int 类,int 长度为 32 字节,short、byte、char在做移位之前会自动转换为int型,因此与int规则一致, 在做完移位运算后,short、byte、char类型都将变成int型数据(转换过程中需要考虑高位丢失的问题)。下文中实例介绍都是使用 int 类型,如果是long类型,那么在移位取余时,数据长度替换为64即可。

运算规则:按二进制形式把所有的数字向左移动对应的位数,丢弃左边(高位)指定位数,右边(低位)补0。
实例:定义一个 int 类型数字,int intValue = 12345678,那么这个数字在二进制中的形式如下:
int intValue = 12345678;
// 以下两个方法都可以打印出二进制形式,不过高位0已被舍弃
System.out.println(Integer.toString(intValue, 2));
System.out.println(Integer.toBinaryString(intValue));
// 输出 ==> 101111000110000101001110
intValue << 1,左移1位:

 

 

由上图可以看出,在左移1位后,转化为10进制,结果为24691356,刚好是原数的2倍,所以在整数乘2的时候也可以使用左移1位来实现,效率更高。
int intValue = 12345678;
// 左移1位
System.out.println("intValue左移1位: " + (intValue << 1));
// 输出 ==> intValue左移1位: 24691356
总结:左移的规则是,丢弃左边(高位)指定位数,右边(低位)补0,当左移位数大于等于当前数据类型长度时进行取余,获取实际的左移位数,实际左移位数 = 左移位数 % 数据类型长度。实际左移过程中,需要考虑到符号位改变的情况。左移可以用在乘2的幂的情况下:4 × 8 = 4 × = 4 << 3。

6.右移运算符 >>
运算规则:丢弃右边(低位)指定位数,左边(高位)补上符号位的值。
实例:还是左移时使用的数字,int intValue = 12345678
intValue >> 1,右移1位:

 

 

由上图可以看出,在右移1位后,转化为10进制,结果为6172839,恰好是原数的一半,所以在整数除2的时候,也可以用右移1位来代替,效率更高。
int intValue = 12345678;
// 右移1位
System.out.println("intValue右移1位:" + (intValue >> 1));
// 输出 ==> intValue右移1位:6172839
总结:右移的规则是,丢弃右边(低位)指定位数,左边(高位)补上符号位的值,右移位数大于等于数据类型的长度时进行取余,获取实际需要移动的位数,实际右移位数 = 右移位数 % 数据类型长度。右移可以用在需要除2的幂的情况下:8 ÷ 4 = 8 ÷ 2^2 = 8 >> 2。

7.无符号右移运算符 >>>
运算规则:与右移基本一致,唯一不同之处在于,在高位补位时,补0而非符号位的值,也就是说,无符号右移是忽略符号,最终结果一定是非负数。
实例:
非负数无符号右移与右移运算符没有分别,负数的无符号右移:

 

 

int intValue = 12345678;

// 正数:无符号右移1位
System.out.println("intValue无符号右移1位:" + (intValue >>> 1));
// 输出 ==> intValue无符号右移1位:6172839
// 负数:无符号右移31位
System.out.println("负intValue无符号右移31位:" + (-intValue >>> 31));
// 输出 ==> 负intValue无符号右移31位:1
所以无符号右移也可以判断出一个数的正负,如果是非负数,那么无符号右移31位等于0,如果是负数,无符号右移31位等于1。

posted @   田园码民  阅读(138)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示