⬛ >> versus >>>
Java的位元運算有兩個很類似的右移運算子,目的是將其唯一的運算元進行往右的位元平移。
當運算元為正時,兩者結果相同,分不出來;遇負數時,兩者結果才有差異。
說明如下:
邏輯右移運算子 >>>: number >>> bits; 表示將2進位數字右移bits位元,左邊補0
算術右移運算子 >> : number >> bits; 也表示將2進位數字右移bits位元,左邊保留目前符號位元
例1: 對於負數,兩種位元右移結果的比較: >> versus >>>
int n = -7;
System.out.printf("n = %d (%x)\n",n,n);
System.out.printf("n >> 2 = %d (%x)\n",n >> 2,n >> 2);
System.out.printf("n >>> 2 = %d (%x)\n",n >>> 2, n >>> 2);
則3行輸出如下:
n = -7 (fffffff9) // 二進位表示為 1111 1111 1111 1111 1111 1111 1111 1001
n >> 2 = -2 (fffffffe) // 二進位表示為 1111 1111 1111 1111 1111 1111 1111 1110
n >>> 2 = 1073741822 (3ffffffe) // 二進位表示為 0011 1111 1111 1111 1111 1111 1111 1110
其中,第一行二進位為原始數字;
第二行運算將二進位數字往右平移2位元,左邊補目前符號位元1;
第三行運算將二進位數字往右平移2位元,左邊補0
註: 須要維持正負號的右移運算可用 >>
註: 不補符號位元的右移運算可用 >>>
註: 至於左移運算子,因為右邊永遠補0,沒有其他選擇,所以只有一種 << 運算子
⬛ & versus && as well as | versus ||
Java的且及或運算也各有很接近的運算子,其說明如下:
邏輯且: b = bool_1 && bool_2; // 有短路求值,遇bool_1假,不看bool_2值,一律回傳假
位元且: b = bool_1 & bool_2; // 無短路求值
n = number_1 & number_2;
邏輯或: b = bool_1 || bool_2; // 有短路求值,遇bool_1真,不看bool_2值,一律回傳真
位元或: b = bool_1 | bool_2; // 無短路求值
n = number_1 | number_2;
例2: 對於數字及布林值,兩種【且】運算的比較: & versus &&
System.out.printf("true & false = %b\n", true & false);
System.out.printf("true && false = %b\n", true && false);
System.out.printf("1100 & 0101 = %x\n", 0b1100 & 0b0101);
//System.out.printf("1100 && 0101 = %d\n", 0b1100 && 0b0101);
則3行輸出如下:
true & false = false
true && false = false
1100 & 0101 = 4 // 二進位表示 為0100
其中,第一行兩布林值進行【位元且】運算,只當兩布林值同時為真時才為真,故得到假;
第二行兩布林值進行【邏輯且】運算,只當兩布林值同時為真時才為真,故得到假;
第三行兩數字進行【位元且】運算,只留下兩數字同時為1的位元才為1,故得到0100=4。
另外,第四行語法不允許兩數字進行【邏輯且】運算,故註解起來。
例3: 對於數字及布林值,兩種【或】運算的比較: | versus ||
System.out.printf("true | false = %b\n", true | false);
System.out.printf("true || false = %b\n", true || false);
System.out.printf("1100 | 0101 = %x\n", 0b1100 | 0b0101);
//System.out.printf("1100 || 0101 = %d\n", 0b1100 || 0b0101);
則3行輸出如下:
true | false = true
true || false = true
1100 | 0101 = d // 二進位表示 為1101
其中,第一行兩布林值進行【位元或】運算,只當兩布林值同時為假時才為假,故得到真;
第二行兩布林值進行【邏輯或】運算,只當兩布林值同時為假時才為假,故得到真;
第三行兩數字進行【位元或】運算,只留下兩數字同時為0的位元才為0,故得到1101=13=d。
另外,第四行語法不允許兩數字進行【邏輯或】運算,故註解起來。
例4: 對於布林值,短路求值與否的【且】運算比較: & versus &&
b = b1 = b2 = true;
b = (b1=false) & (b2=false);
System.out.printf("no short circuit evaluation: b:%b, b1:%b, b2:%b\n",b,b1,b2);
b = b1 = b2 = true;
b = (b1=false) && (b2=false);
System.out.printf("use short circuit evaluation:b:%b, b1:%b, b2:%b\n",b,b1,b2);
則2行輸出如下:
no short circuit evaluation: b:false, b1:false, b2:false
use short circuit evaluation:b:false, b1:false, b2:true
其中,第一行輸出不作短路求值,所以b1及b2皆接收到false值;
第二行輸出有作短路求值,所以b1接收回傳false值後,不須進行b2=false運算,就可判定b為假,故b2維持true值。
例5: 對於布林值,短路求值與否的【或】運算比較: | versus ||
b = b1 = b2 = false;
b = (b1=true) | (b2=true);
System.out.printf("no short circuit evaluation: b:%b, b1:%b, b2:%b\n",b,b1,b2);
b = b1 = b2 = false;
b = (b1=true) || (b2=true);
System.out.printf("use short circuit evaluation:b:%b, b1:%b, b2:%b\n",b,b1,b2);
則2行輸出如下:
no short circuit evaluation: b:true, b1:true, b2:true
use short circuit evaluation:b:true, b1:true, b2:false
其中,第一行輸出不作短路求值,所以b1及b2皆接收到true值;
第二行輸出有作短路求值,所以b1接收回傳true值後,不須進行b2=true運算,就可判定b為真,故b2維持false值。
註: 數字的且/或運算只能用 &, |
註: 條件式或布林值的且/或運算,若須要短路求值可用 &&, ||
註: 條件式或布林值的且/或運算,若不須要短路求值可維持 &, |
參考:
1.StackOverflow: Difference between >>> and >>
2.Wiki: Short Circuit Evaluation
java right shift and and/or operators in comparison
訂閱:
張貼留言 (Atom)
Linked Lists from C to Java
「 C Pointer Concepts in Java 」一文提到 Java 沒有指標型別 (pointer type) ,但有參照型別 (reference type) 的設計。在遇到須要處理鏈結清單 (linked list)、圖形 (graph) 等資料結構時,Java ...
沒有留言:
張貼留言