天天看點

Java中的與、或、非以及異或(& | ~ ^)運算符的運算原理

首先,我們要知道Java存儲資料是儲存的補碼,如果對原碼、反碼以及補碼不太懂,可以參考我的另一篇部落格。

1. Java的 與( & ) 運算

所有的邏輯運算都是按位計算的,是以第一步就是先把資料轉成二進制,然後相應位進行 與 運算,具體運算過程可以看下圖中的注釋。

Java中的與、或、非以及異或(& | ~ ^)運算符的運算原理

2. Java的 或( | ) 運算

或運算類似,看下圖

Java中的與、或、非以及異或(& | ~ ^)運算符的運算原理

 3. Java的 非( ~ ) 運算

非運算類似,看下圖。不知道你有沒有看出規律,正數的非運算結果都是本身先加1,然後加個負号;負數的補碼也是本身取絕對值,然後減1。可以去驗證一下 非 運算這個規律。

Java中的與、或、非以及異或(& | ~ ^)運算符的運算原理

4. Java的 異或 (^) 運算

異或運算是一個比較奇特的運算原理,首先也是按位運算,然後兩個數相同結果為0,不同為1,即 1^1 = 0,1^0=1,0^1=1,0^0=0。如果學過數字電路這門課的話,你會知道最基本的三種邏輯運算是 與 或 非,異或是可以用這三種基本邏輯運算表示的,那麼怎麼表示呢?如果學過數字電路,是可以畫卡諾圖來用 與 或 非表示異或的,在這裡我們就麻煩點、但是通俗易懂地解釋一下異或怎麼用 與 或 非來表示。

a b a&b a|b (~a)&b a&(~b) (~a)|b a|(~b) a^b
1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1 1

如表,a和b之間使用基本運算的組合總共有6種,(~a)&(~b)和a&b的效果是一樣,(~a)|(~b)和a|b的效果是一樣,而且~(a&b)和(~a)|(~b)是一樣的,是以隻有上面六種組合。上面6中組合可以怎麼組合得到異或結果呢?因為組合有點多,我們通過代碼來周遊,代碼如下。

class Imple{
    static void xor(int[][] arr){
        byte f_and = 0;
        byte f_or = 0;
        for (int k = 0; k < 6; k++) {
            for (int l = k+1; l < 6; l++) {
                if((arr[k][0] & arr[l][0]) == arr[6][0]){
                    f_and += 1;
                    for (int i = 1; i < 4; i++) {
                        if((arr[k][i] & arr[l][i]) == arr[6][i]){
                            f_and += 1;
                        }
                    }
                }
                if((arr[k][0] | arr[l][0]) == arr[6][0]){
                    f_or += 1;
                    for (int i = 1; i < 4; i++) {
                        if((arr[k][i] | arr[l][i]) == arr[6][i]){
                            f_or += 1;
                        }
                    }
                }
                if(f_and == 4){
                    System.out.println("異或運算可表達為第" + (k+1) + "個表達式和第" + (l+1) + "個表達式相與");
                }else if(f_or == 4){
                    System.out.println("異或運算可表達為第" + (k+1) + "個表達式和第" + (l+1) + "個表達式相或");
                }
                f_and = 0;
                f_or = 0;
            }
        }
    }
    static int[][] initArray(){
        int[][] com = new int[7][4];
        int a;
        int b;
        for (int j = 0; j < 4; j++) {
            a = j/2;
            b = j%2;
            com[0][j] = a&b;
            com[1][j] = a|b;
            com[2][j] = (~a)&b;
            com[3][j] = a&(~b);
            com[4][j] = (~a)|b;
            com[5][j] = a|(~b);
            com[6][j] = a^b;
        }
        return com;
    }
    public static void main(String[] args) {
        int[][] arr;
        arr = initArray();
        xor(arr);
    }
}
           

運作結果如下圖,可知第三個表達式和第四個表達式進行 或 運算可以得到異或的效果,也就是 a^b = ((~a)&b) | (a&(~b))  現在你可以反驗證。 

Java中的與、或、非以及異或(&amp; | ~ ^)運算符的運算原理

上面的表達式其實就是課本中對異或的定義,但是上面的公式似乎還不夠簡潔 ,兩個數異或,還有沒有其它表達呢?如下圖

Java中的與、或、非以及異或(&amp; | ~ ^)運算符的運算原理

是以我們可以進一步表示異或運算為 a^b = |a - b| (相減取絕對值不是十進制,要先轉換為二進制,然後對應位相減取絕對值)