­

你不會還不知道按位取反運算的原理吧

引入

首先來看一個程序,分別打印4-4的取反運算結果,代碼:

public static void main(String[] args) {
    System.out.println(~4);
    System.out.println(~(-4));
}

不妨思考一下結果,如果結果是-4和4的話,那請繼續看下去吧.顯然結果不是你想的那樣,一起看下:

187MFUkJ
187MFUkJ

沒錯,結果就是-5和3(可不是相反數那麼簡單的喲),這裡先告訴一個萬能計算公式,要計算一個整數的取反運算,比如x,那麼:

~x = -(x+1);

理解

雖然有計算公式,相信你還是跟我一樣,想弄清楚為什麼是這樣的結果.
首先來看,~這個計算符號的定義是什麼?
按照我平時的理解,當我使用~按位取反運算的時候,計算機會將操作數所對應的二進制表達式的每一個位進行取反計算,取反後所得到的值就是~按位取反的運算結果(這點沒問題),但是怎麼去理解呢,我們來具體分析下.

在這之前,先說一下計算機中的數據表示:
我們平時學習的二進制表示有三種形式:原碼,反碼和補碼;
然而計算機只認識補碼,原碼和反碼只是人們方便計算人為定義的,所以計算機中的所有計算二進制的輸入輸出都是補碼的形式,理解到這點,就可以繼續往下看了.

還是上面的程序,我們對4進行取反運算,過程如下:

  1. 4的二進制表示(補碼): 0 100
  2. 計算機對它進行按位取反: 1 011
  3. 這時計算機將計算結果反饋給我們,得到的答案是: -5

可能你還是納悶,為什麼1011就得到-5了呢,不應該是-3嗎?
回到剛剛說的,計算機中所有二進制輸出都是補碼的形式,因此1011是某一個數的補碼錶示形式,我們需要把他轉成我們能理解的二進制:

  1. 首先看補碼1 011,最高位為1,表示是一個負數,因此符號位不變,然後減1,得到反碼(補碼 = 反碼 + 1,反之): 1 010;
  2. 將反碼1 010符號位除開,按位取反得到原碼: 1 101,這不就是-5了嘛.

同理,我們再看-4取反:

  1. 64的二進制表示(補碼): 1 100
  2. 計算機對它進行按位取反: 0 011
  3. 這時計算機將計算結果反饋給我們,得到的答案是: 3

那為什麼又是3呢?
很簡單,補碼0 011最高位為0,說明是正數,而正數的原碼和補碼是一樣的,所以直接等於3.

public static void main(String[] args) {
    System.out.println(~4);
    //補碼: 0 100
    //取反: 1 011
    //反碼: 1 010
    //原碼: 1 101 = -5
    System.out.println(~(-4));
    //1 100
    //1 011
    //補碼: 1 100
    //取反: 0 011
    //原碼: 0 011 = 3
}

> 歡迎關注 [碼之淚殤](//www.gongsir.club)