1. 程式人生 > >Java位移運算

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

至此,例子解析完畢,有問題請指教。