2017年5月17日 星期三

java right shift and and/or operators in comparison

⬛ >> 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

沒有留言: