Java中的位运算符号详解(&、|、^、~、<<、>>、>>>)(转载)
位运算符号概览
符号 | 描述 | 运算规则 |
---|---|---|
& | 与 | 两个位都为1时,结果才为1 |
| | 或 | 两个位都为0时,结果才为0 |
^ | 异或 | 两个位相同为0,不同为1 |
~ | 取反 | 所有位置0变1,1变0 |
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
>> | 带符号右移 | 各二进位全部右移若干位,低位丢弃,高位补为符号位 |
>>> | 无符号右移 | 各二进位全部右移若干位,低位丢弃,高位补0 |
还有两个符号,并不是位运算符,但是容易与位运算符混淆,后面将与其相似的位运算符进行一并讲解:
符号 | 描述 | 运算规则 |
---|---|---|
&& | 逻辑与 | 左右表达式均为true时,运算最终结果才为true |
|| | 逻辑非 | 左右表达式只要有一个为true,运算最终结果就为true |
一个工具
下面的函数可以帮助我们打印Java中int整型的在底层的32位信息,后面可以使用该工具对程序进行调试:
public static void print(int num) {
for (int i = 31; i >= 0; i--) {
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
System.out.println();
}
// print(1); --> 00000000000000000000000000000001
// print(-1); --> 11111111111111111111111111111111
// print(Integer.MAX_VALUE); --> 01111111111111111111111111111111
// print(Integer.MAX_VALUE); --> 10000000000000000000000000000000
下面开始对每个符号进行介绍。
按位与(&)、逻辑与(&&)
**按位与(&)**的具体运算规则为:
1 & 1 = 1 1 & 0 = 0 0 & 1 = 0 0 & 0 = 0
// 举例:
print(123); // 00000000000000000000000001111011
print(321); // 00000000000000000000000101000001
print(a & b); // 00000000000000000000000001000001
// 任何数与0相与都等于0
// 任何数与自己相与都等于自己
在Java中,(&)不仅可以作为位运算符号,同样也可以作为逻辑与符号,
要注意:(&&)并不是位运算符号,不可以参与位运算!
**逻辑与(&)、逻辑与(&&)**的具体运算规则为:
true & true = true true & false = false false & true = false false & false = false
true && true = true true && false = false false && true = false false && false = false
两者的区别在于:
**逻辑与(&)**在运算时,不论(&)前面的表达式的结果是否为false,(&)后面的表达式都会执行运算;
而**逻辑与(&&)**在运算时,如果(&&)前面的表达式的结果为false,则(&&)后面的表达式就不会执行运算。
按位或(|)、逻辑或(||)
**按位与(&)**的具体运算规则为:
1 | 1 = 1 1 | 0 = 1 0 | 1 = 1 0 | 0 = 0
// 举例:
print(123); // 00000000000000000000000001111011
print(321); // 00000000000000000000000101000001
print(a | b); // 00000000000000000000000101111011
// 任何数与0相或都等于自身
// 任何数与自己相或都等于自己
在Java中,(|)不仅可以作为位运算符号,同样也可以作为逻辑与符号。
要注意:(||)并不是位运算符号,不可以参与位运算!
**逻辑或(|)、逻辑或(||)**的具体运算规则为:
true | true = true true | false = true false | true = true false | false = false
true || true = true true || false = true false || true = true false || false = false
两者的区别在于:
**逻辑或(|)**在运算时,不论(|)前面的表达式的结果是否为true,(|)后面的表达式都会执行运算;
而**逻辑或(||)**在运算时,如果(||)前面的表达式的结果为true,则(||)后面的表达式就不会执行运算。
异或(^)
**异或(^)**的具体运算规则为:
1 ^ 1 = 0 1 ^ 0 = 1 0 ^ 1 = 1 0 ^ 0 = 0
// 即相同为0,不同为1
// 举例:
print(123); // 00000000000000000000000001111011
print(321); // 00000000000000000000000101000001
print(a ^ b); // 00000000000000000000000100111010
// 任何数与0异或都等于自身
// 任何数与自己异或都为0
取反(~)
**取反(~)**的具体运算规则为:
~1 = 0 ~0 = 1
// 举例:
print(123); // 00000000000000000000000001111011
print(~a); // 11111111111111111111111110000100
// 符号位也取反
**取反(~)**可以用来求相反数:
// 一个32整数,取反再+1,就是该数的相反数,效果等同于加负号(-)
int a = 123;
System.out.println(a); // 123
System.out.println(~a+1); // -123
说明:
由于Java中int类型的整数范围为−2^31 ∼ 2^31 − 1,负数的个数比正数多一个,这样就导致,所有的正数都有相应的负的相反数,但是并不是所有的负数都有正的相反数:
a = Integer.MIN_VALUE;
System.out.println(a); // -2147483648
print(a); // 10000000000000000000000000000000
System.out.println(~a+1); // -2147483648
print(~a + 1); // 10000000000000000000000000000000
// Java中int整数最小值的相反数还是其自身
// 如果一定需要对int整数最小值求相反数,请将int类型换为long类型
左移(<<)
左移表示的是某数的各二进位全部左移若干位,高位丢弃,低位补0
// 举例:
print(123); // 00000000000000000000000001111011
print(123 << 1); // 00000000000000000000000011110110
// 整体左移1位,高位丢弃,低位补0
应用:
// 左移1位相当于在原数的基础上乘以2
System.out.println(123); // 123
System.out.println(123<<1); // 246
// 左移2位相当于在原数的基础上乘以4
System.out.println(2); // 2
System.out.println(2<<2); // 8
// 左移3位、4位...以此类推
带符号右移(>>)、无符号右移(>>>)
**带符号右移(>>)**指的是各二进位全部右移若干位,低位丢弃,高位补为符号位
**无符号右移(>>>)**指的是各二进位全部右移若干位,低位丢弃,高位补0
int a = 123;
print(a); // 00000000000000000000000001111011
print(a>>2); // 00000000000000000000000000011110
print(a>>>2); // 00000000000000000000000000011110
int b = -123;
print(b); // 11111111111111111111111110000101
print(b>>2); // 11111111111111111111111111100001
print(b>>>2); // 00111111111111111111111111100001
// 区别就在于:一个高位用符号位补,一个高位用0补
Java中没有(<<<)符号!!!
转载于:https://blog.csdn.net/qq_44494578/article/details/125230581
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?