核心區別一覽
| 運算符 | 名稱 | 高位補齊規則 | 適用類型 | 典型場景 |
>> | 算術右移 / 有符號右移 | 複製符號位(正數補 0,負數補 1) | 所有整數類型 | 保持正負號的除以 2^n |
>>> | 邏輯右移 / 無符號右移 | 固定補 0 | 所有整數類型(Java 特有) | 位掩碼處理、無符號數運算 |
二進制圖解(以 8 位為例)
原數: 1001 1101 (十進制 -99,最高位 1 表示負數)
>> 1 (算術右移):
步驟1: 1100 1110 (符號位 1 補齊)
步驟2: 1110 0111 (再右移 1 位)
結果: 1110 0111 (十進制 -25,符號保持)
>>> 1 (邏輯右移):
步驟1: 0100 1110 (固定補 0)
步驟2: 0010 0111 (再右移 1 位)
結果: 0010 0111 (十進制 39,變為正數!)
為什麼 Java 有 >>> 而 C/C++ 沒有?
- Java 無
unsigned 關鍵字,所有整數類型均為有符號
- C/C++ 有
unsigned int,對無符號數右移編譯器自動執行邏輯右移
- Java 需顯式運算符區分兩種語義
實戰陷阱與最佳實踐
陷阱 1:負數右移後判斷奇偶
int n = -5; // 1111...1011
boolean odd = (n & 1) == 1; // 正確:最低位決定奇偶
boolean odd2 = (n >> 1) & 1; // 錯誤!算術右移補 1,破壞原意
陷阱 2:哈希碼/索引計算
// 錯誤:負數 hashCode 導致負索引
int index = key.hashCode() >> 1;
// 正確:無符號右移保證非負
int index = key.hashCode() >>> 1;
// 或更常用:
int index = (key.hashCode() & 0x7FFFFFFF) % size;
陷阱 3:長整型合成
long combined = ((long)high << 32) | (low & 0xFFFFFFFFL);
// 取高 32 位時必須用 >>>,否則符號擴展導致錯誤
int high = (int)(combined >>> 32);
左移運算符 <<
- 只有
<<,無 <<<
- 低位補 0,高位丟棄
- 等同於乘以 2^n(溢出按模 2^32/2^64 環繞)
面試必考點
-1 >> 1 = ? (答案:-1,全 1 右移仍全 1)
-1 >>> 1 = ? (答案:2147483647,即 0x7FFFFFFF)
5 >> 2 vs 5 >>> 2 (正數時結果相同,均為 1)
- 如何用位運算實現無符號整數除以 2? (
n >>> 1)