Java位運算總結:位運算用途普遍

前天幾天研究了下JDK的Collection接口,原本準備接着研究Map接口,但是一查看HashMap類源碼傻眼咯,處處是位運算實現,因此我以爲仍是有必要先補補位運算知識,否則代碼看起來有點費力。今天系統研究了下,現記錄以下。php

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

還須要明白一點的是:計算機表示數字正負不是用+ -加減號來表示,而是用最高位數字來表示,0表示正,1表示負java

因此好比-4用二進制原碼錶示就是1111 1111 1111 1111 1111 1111 1111 1100app

 

下面根據實例一個一個的來講明各類位運算的運算規則:
位與&(真真爲真 真假爲假 假假爲假)
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
結果:6ui

位非~(取反碼)【注: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
結果:-5url

位異或^(真真爲假 真假爲真 假假爲假)
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
結果:2htm

有符號右移>>(若正數,高位補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 
等等

固然還有牛人使用位運算來實現權限控制,加密技術,裏面的奧祕深不可測

來源:

相關文章
相關標籤/搜索