无符号整数(逻辑右移)`>>`
- 右移n的操作就是二进制右边n位舍弃,左面补n个0
- 十进制的结果可以记为:右移n位,即为整数除以2的n次方,结果向下取整(比如
19 >> 2 => 19 / 4 => 4.75 => 4
)
有符号整数(算术右移)`>>>`
- 右移n的操作就是二进制右边n位舍弃,左面补n个符号位的值(正数补 0,负数补1)
- 十进制的结果可以记为:右移n位,即为整数除以2的n次方,结果向下取整(比如
-19 >> 2 => -19 / 4 => -4.75 => -5
)
为什么不只搞1个右移操作符?
可移植性与定义不明确 在 C/C++ 中,>> 用于有符号整数时,标准规定是“实现定义”
也就是说不同编译器、不同 CPU,结果可能不同可控性(语言语义明确 vs 智能猜测)
语言设计者倾向于:
- 明确告诉你:你写
>>
,你就知道它是啥行为 - 而不是根据类型“猜测”你想干啥(避免不确定行为)
- 类型推断可能不明确
cpp
auto x = foo();
x >> 2;
此时你可能都不知道 x 的类型是 int、unsigned int 还是 char,那语言怎么判断你到底是想做逻辑右移还是算术右移?强制明确操作反而更安全。
这里针对3,其实Java这种强类型语言是知道类型的,为什么不设计1个右移符号呢?
Java 的设计哲学是:语义明确、行为可预期、绝不“猜你的意图”,也就是回到第2点上
“强类型 ≠ 自动猜测操作行为”
“强类型 + 显式操作 = 安全 + 可维护性 + 无歧义”
所以Java中是没有无符号整数的,所有整数类型(int, long)都被视为有符号类型
右移的常见操作
除以2的幂次
提取整数x的i位二进制
⚠️这里的i从0开始 (x >> i) & 1
可以配合数据的长度遍历每一位
java
public class BinaryBitTraversal {
public static void main(String[] args) {
int x = 19;
int bitLength = Integer.toBinaryString(x).length();
for (int i = 0; i < bitLength; i++) {
int bit = (x >> i) & 1;
System.out.printf("第 %d 位: %d\n", i, bit);
}
}
}
提取整数x的多位二进制(从i到j)
java
public class BinaryBitExtraction {
public static void main(String[] args) {
int x = 0b110101; // 二进制数 110101,十进制为 53
int i = 1;
int j = 3;
// 右移 i 位
int shifted = x >> i;
// 创建掩码
int mask = (1 << (j - i + 1)) - 1;
// 按位与操作
int result = shifted & mask;
System.out.println(Integer.toBinaryString(result)); // 输出10,提取出第 1 到第 3 位
}
}