Java位移運算
最近在補習Java基礎,位移運算是今天的主角。
在此之前我們要先來複習下計算機二進位制的一些概念。
在計算機硬體的世界裡,晶片,處理器等所處理的電訊號都為高低電平,即為10訊號。
順接上篇的一個概念來講下:位元組(byte)
1 byte = 8bit(位) 也就是一個位元組相當於8位(0000 0000)
如果是兩個位元組那就是16位 0000 0000 0000 0000
計算機裡的數也分有符號數跟無符號數, 有符號數的最高位表示符號正0/負1, 而無符號數的最高位跟其他位一樣表示實際的數。
今天只說有符號數:
正數:即最高位為0,比如 0000 0001 為 1
負數:最高位為1, 比如 1000 0011 為 -3
這二進位制是怎麼算成我們生活中常用的十進位制數呢?
1000 0011 = 去掉最高位的1(符號-),剩下的從右往左依次是以2為底數,從0開始間隔為1的冪數
上面的計算是 -(2^0+2^1) = -3
所以 8位有符號數的範圍是[-127, 127]
1111 1111 = -(2^0+2^1+2^2+2^3+2^4+2^5+2^6) = -127
0111 1111 = 2^0+2^1+2^2+2^3+2^4+2^5+2^6 = 127
上面的正數負數皆為我們我們容易理解的寫法。在計算機裡,正數以其原碼,負數以其補碼計算。
原碼,反碼,補碼:
正數的原碼、反碼、補碼皆為其本身;
負數的原碼是其本身,
負數的反碼: 最高位(符號位不變),其餘全部取反, 0變1, 1變0, 1000 0011(原碼) => 1111 1100(反碼)
負數的補碼: 反碼的基礎上加1,這裡有個注意點是,二進位制是逢2進1.
1000 0011(原碼) => 1111 1100(反碼) => 1111 1101(補碼)
講完了上面的基礎,正是進入整體,位移運算,顧名思義:位置的移動運算;
左移:正數負數都在右側補0,負數最高位不變
右移:正數補0, 負數最高位不變,補1
下面有段java的位移運算程式碼:
public static void main(String[] args) { System.out.println(6 >> 2); System.out.println(-8 << 3); System.out.println(-9 >> 1); }
運算結果如下:
1
-64
-5
先來算第一個: 6 >> 2
6的二進位制為: 0000 0110 = 2^1+2^2 = 6
往右移2位,0000 0001 = 2^0 = 1
接著來算第二個:-8 << 3
-8的二進位制: 1000 1000 = -(2^ 3) = -8
負數以補碼形式計算: 1111 0111(反碼) => 1111 1110(補碼)
最高位(符號位)不動,其餘向左移動3位,空位補0, 1111 0000 移動後的依舊為補碼,我們需要還原為原碼:
1111 0000 減1 => 1011 1111 取反 => 1100 0000 = -(2^6) = -64
然後算第三個:-9 >> 1
-9的二進位制: 1000 1001 = -(2^0+2^3) = -9
負數以補碼運算: 1111 0110(反碼)加1=> 1111 0111
最高位不動, 其餘位向右移動1位, 空位補1, 1111 1011(補碼)
1111 1011 減1 => 1111 1010 取反 => 1000 0101 = -(2^0+2^2) = -5
至此,例子解析完畢,有問題請指教。