java 二進制以及二進制運算

雖然現在很少用到二進制,可是一些源碼中會經常遇到,比如:

//HashMap中的hash方法: 
static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

這裏記錄一些二進制知識。

一:負數如何顯示其二進制。

比如5的二進制數爲:00000000  00000000 00000000 00000101(int 類型佔用4個字節,每個字節8位).

那麼-5的二進制是多少了。對於負數,這裏需要理解反碼和補碼
1、所謂原碼就是二進制定點表示法,即最高位爲符號位,“0”表示正,“1”表示負,其餘位表示數值的大小。
2、反碼錶示法規定:正數的反碼與其原碼相同;負數的反碼是對其原碼逐位取反,但符號位除外
原碼10010= 反碼11101 (10010,1爲符號碼,故爲負)
(11101) 二進制= -13 十進制
3、補碼錶示法規定:正數的補碼與其原碼相同;負數的補碼是在其反碼的末位加1。
舉一例,我們來看整數-5在計算機中如何表示。
假設這也是一個int類型,那麼:
1、先取1的原碼:00000000 00000000 00000000 00000101
2、得反碼: 11111111 11111111 11111111 11111010
3、得補碼: 11111111 11111111 11111111 11111011

可以在控制檯輸出測試:

輸出-5的二進制數
System.out.println(Integer.toBinaryString(-5));// 11111111 11111011

二:二進制常用的運算。(^異或運算,與運算&,|運算,左移運算<<,右移運算(有符號)>>,無符號又移>>>)

1.^異或運算。二進制數 相同爲0.不同爲1;

/**
	 *  ^異或運算。二進制數 相同爲0.不同爲1; 
	 */
	@Test
	public void testOr(){
		int first=3;//                  0011------------3
		int second=4;//                 0100------------4
		int three=first^second;//       0111------------7
		System.out.println(three);//7
	}

2.&運算。只有都爲1時才爲1.否則爲0

@Test
	/**
	 * 二進制數 只有都爲1時才爲1.否則爲0
	 */
	public void testAnd(){
		int first=12;//-----------------00001100   值爲 12
		int second=22;//----------------00010100   值爲 22
		int three=first&second;//-------00000100   值爲 4
		System.out.println(three);//---4
	}

3.|運算。(參加運算的兩個對象只要有一個爲1,其值爲1。)

@Test  //(參加運算的兩個對象只要有一個爲1,其值爲1。)
	public void testOrAnd(){
		System.out.println(5|2);//7
		System.out.println(Integer.toBinaryString(5));// 00000000 00000000 00000000 00000101
		System.out.println(Integer.toBinaryString(2));// 00000000 00000000 00000000 00000010
		System.out.println(Integer.toBinaryString(7));// 00000000 00000000 00000000 00000111
	}

4.左移運算(<<)

   如果是整數,直接轉爲二進制數進行左移,低位補0.

  如果是負數。首先也要轉爲二進制數(通過反碼,補碼機制)。轉移完後,將二進制數加一,取反碼。得最終的結果

  下面給的例子是 -5<< 結果爲20.

/**
	 * 左移運算(<<)   二進制數向左移動,低位用0補齊
	 * 反碼是除符號位(最高位)外取反
	 */
	@Test
	public void testLeftMove(){
		int first=33;//              00100001 值爲33
		int two=first<<2;//          10000100 值爲132
		System.out.println(two);  //132
		//如果是負數
		//-5 的二進制,先是算5 的二進制       00000000 00000000 00000000 00000101  然後進行取反(除最高位外)
		//-5的反碼是                        11111111 11111111 11111111 11111010
		//   補碼    反碼+1                 11111111 11111111 11111111 11111011
		//-----------------------------------計算 -5<<2的值----------------------------
		//首先-5的補碼左移兩位,低位補0得:
		//                              11111111 11111111 11111111 11101100
		//然後 減一得:
		//                             11111111 11111111 11111111 11101011
		//最後取反即可:
		//                             00000000 00000000 00000000 00010100  值爲20
		  System.out.println(-5<<2);//20
		System.out.println(Integer.toBinaryString(-5));//11111111 11111111 11111111 11111011
	}

5.右移運算(>>).如果是正數,高位補0.如果是負數,高位補1。

    都是先轉換爲二進制再進行位移運算。如果是負數,也是要藉助反碼和補碼。

/**
	 * 右移(>>) 二進制數整體向右移動。如果是正數,高位補0.如果是負數,高位補1
	 */
	@Test
	public void testRightMove(){
		//-5的二進制       11111111 11111111 11111111 11111011
		//右移1位              11111111 11111111 11111111 111111101
		
		System.out.println(-5>>1);//-3    
		System.out.println(Integer.toBinaryString(-3));//11111111111111111111111111111101
		
		System.out.println(-2147483647>>5);
		System.out.println(Integer.toBinaryString(-2147483647>>5));
		System.out.println(Integer.toBinaryString(-2147483647));
	}

6.無符號的右移運算(>>>)

  即無論是正數還是負數,高位都補0.

下面代碼可見>>>運算不再採用補碼和反碼機制了。不管是正數還是負數,最終都是正數。所以直接    將轉移後的二進制轉換爲正數。如果是負數採用>>>的話,也爲正數了。

	/**
	 * 無論正負高位同一補0。
	 */
	@Test
	public void testRightMoveThree(){
		System.out.println(-5>>>2);                               //1073741822
		System.out.println(Integer.toBinaryString(-5));           //11111111 11111111 11111111 11111011
		System.out.println(Integer.toBinaryString(1073741822));//   00111111 11111111 11111111 11111110
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章