Java位元運算總結:位元運算用途廣泛《轉》

來源:互聯網
上載者:User

標籤:

前天幾天研究了下JDK的Collection介面,本來準備接著研究Map介面,可是一查看HashMap類源碼傻眼咯,到處是位元運算實現,所以我覺得還是有必要先補補位元運算知識,不然代碼看起來有點費力。今天系統研究了下,現記錄如下。

       首先要明白一個概念,Java位元運算是針對於整型資料類型的二進位進行的移位操作。主要包括位與、位或、位非,有符號左移、有符號右移,無符號右移等等。需要注意一點的是,不存在無符號左移<<<運算子。根據位元運算的概念規定,我們首先需要弄明白兩個問題,java有哪些資料類型是整數資料型別和各數字進位之間轉換問題。Java整數資料型別有:byte、char、short、int、long。要把它們轉換成二進位的原碼形式,必須明白他們各占幾個位元組。我們都知道,一個位元組佔8位。
      資料類型                           所佔位元
      byte                                       8 
      boolean                                8
      short                                    16
      int                                         32 
      long                                      64 
      float                                      32 
      double                                  64 
      char                                     16

還需要明白一點的是:電腦表示數字正負不是用+ -加減號來表示,而是用最高位元字來表示,0表示正,1表示負

所以比如-4用二進位原碼錶示就是1111 1111 1111 1111 1111 1111 1111 1100

 

下面根據執行個體一個一個的來說明各種位元運算的運算規則:
位與&(真真為真 真假為假 假假為假)
4&6
0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0000 0110
0000 0000 0000 0000 0000 0000 0000 0100
結果:4

位或|(真真為真 真假為真 假假為假)
4|6
0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0000 0110
0000 0000 0000 0000 0000 0000 0000 0110
結果:6

位非~(取反碼)【註:Java中正數的最高位為0,負數最高位為1,即最高位決定正負符號】
~4
0000 0000 0000 0000 0000 0000 0000 0100
1111 1111 1111 1111 1111 1111 1111 1011

解碼:先取反碼,再補碼
0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0000 0101
結果:-5

位異或^(真真為假 真假為真 假假為假)
4^6
0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0000 0110
0000 0000 0000 0000 0000 0000 0000 0010
結果:2

有符號右移>>(若正數,高位補0,負數,高位補1)
-4>>2
1111 1111 1111 1111 1111 1111 1111 1100   原碼
1111 1111 1111 1111 1111 1111 1111 1111   右移,最左邊空出兩位按規則負數空位補1
0000 0000 0000 0000 0000 0000 0000 0000   解碼
0000 0000 0000 0000 0000 0000 0000 0001   補碼(補碼即最後一位+1)
結果:-1


有符號左移<<(若正數,高位補0,負數,高位補1)
-4<<2
1111 1111 1111 1111 1111 1111 1111 1100   原碼
1111 1111 1111 1111 1111 1111 1111 0000   左移,最右邊空出兩位補0
0000 0000 0000 0000 0000 0000 0000 1111   解碼
0000 0000 0000 0000 0000 0000 0001 0000   補碼
結果:-16

無符號右移>>>(不論正負,高位均補0)
-4>>>2
1111 1111 1111 1111 1111 1111 1111 1100   原碼
0011 1111 1111 1111 1111 1111 1111 1111   右移(由於高位均補0,故>>>後的結果一定是正數)
結果:1073741823

由於資料類型所佔位元組是有限的,而位移的大小卻可以任意大小,所以可能存在位移後超過了該資料類型的表示範圍,於是有了這樣的規定:
如果為int資料類型,且位移位元大於32位,則首先把位移位元對32模數,不然位移超過總位元沒意義的。所以4>>32與4>>0是等價的。

如果為long類型,且位移位元大於64位,則首先把位移位元對64模數,若沒超過64位則不用對位元模數。

如果為byte、char、short,則會首先將他們擴充到32位,然後的規則就按照int類型來處理。

 

學到這裡,我想你也可能會問,位元運算到底有什麼用途或者有哪些情境可以應用到它。因為位元運算的運算效率比直接對數字進行加減乘除高很多,所以當出現以下情景且對運算效率要求較高時,可以考慮使用位元運算。不過實際工作中,很少用到它,我也不知道為什麼很少有人用它,我想應該是它比較晦澀難懂,如果用它來進行一些運算,估計編寫的代碼的可讀性會不強,畢竟我們寫的代碼不僅僅留給自己一個人看。
1.  判斷int型變數a是奇數還是偶數    
     a&1  = 0 偶數 
     a&1 =  1 奇數 
2.  求平均值,比如有兩個int類型變數x、y,首先要求x+y的和,再除以2,但是有可能x+y的結果會超過int的最大表示範圍,所以位元運算就派上用場啦。
      (x&y)+((x^y)>>1); 
3.  對於一個大於0的整數,判斷它是不是2的幾次方
    ((x&(x-1))==0)&&(x!=0); 
4.  比如有兩個int類型變數x、y,要求兩者數字交換,位元運算的實現方法:效能絕對高效
    x ^= y; 
    y ^= x; 
    x ^= y; 
5. 求絕對值
    int abs( int x ) 
   { 
     int y ; 
     y = x >> 31 ; 
    return (x^y)-y ;        //or: (x+y)^y 
   }
6.  模數運算,採用位元運算實現:
     a % (2^n) 等價於 a & (2^n - 1) 
7.  乘法運算   採用位元運算實現
     a * (2^n) 等價於 a << n
8.   除法運算轉化成位元運算
      a / (2^n) 等價於 a>> n 
9.   求相反數
      (~x+1) 
10  a % 2 等價於 a & 1 

等等
當然還有牛人使用位元運算來實現許可權控制,加密技術,裡面的奧秘深不可測啊!哈哈。

原文串連: http://www.52ij.com/jishu/102.html 

Java位元運算總結:位元運算用途廣泛《轉》

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.