Java位運算小節

2019新春支付寶紅包技術大揭祕在線峯會將於03-07日開始,點擊這裏報名屆時便可參與大牛互動。java

位運算表達式由操做數和位運算符組成,實現對整數類型的二進制數進行位運算。位運算符能夠分爲邏輯運算符(包括~、&、|和^)及移位運算符(包括>>、<<和>>>)。算法

1)左移位運算符(<<)能將運算符左邊的運算對象向左移動運算符右側指定的位數(在低位補0)。
2)「有符號」右移位運算符(>>)則將運算符左邊的運算對象向右移動運算符右側指定的位數。 「有符號」右移位運算符使用了「符號擴展」:若值爲正,則在高位插入0;若值爲負,則在高位插入1。
3)Java也添加了一種「無符號」右移位運算符(>>>),它使用了「零擴展」:不管正負,都在高位插入0。這一運算符是C或C++沒有的。
4)若對char,byte或者short進行移位處理,那麼在移位進行以前,它們會自動轉換成一個int。 只有右側的5個低位纔會用到。這樣可防止咱們在一個int數裏移動不切實際的位數。 若對一個long值進行處理,最後獲得的結果也是long。此時只會用到右側的6個低位,防止移動超過long值裏現成的位數。 但在進行「無符號」右移位時,也可能遇到一個問題。若對byte或short值進行右移位運算,獲得的可能不是正確的結果(Java 1.0和Java 1.1特別突出)。 它們會自動轉換成int類型,並進行右移位。但「零擴展」不會發生,因此在那些狀況下會獲得-1的結果。

在進行位運算時,須要注意幾點:數組

(1)>>>和>>的區別是:在執行運算時,>>>運算符的操做數高位補0,而>>運算符的操做數高位移入原來高位的值。
(2)右移一位至關於除以2,左移一位(在不溢出的狀況下)至關於乘以2;移位運算速度高於乘除運算。
(3)若進行位邏輯運算的兩個操做數的數據長度不相同,則返回值應該是數據長度較長的數據類型。
(4)按位異或能夠不使用臨時變量完成兩個值的交換,也可使某個整型數的特定位的值翻轉。
(5)按位與運算能夠用來屏蔽特定的位,也能夠用來取某個數型數中某些特定的位。
(6)按位或運算能夠用來對某個整型數的特定位的值置1。

位運算符的優先級

~的優先級最高,其次是<<、>>和>>>,再次是&,而後是^,優先級最低的是|。

位運算的應用

1.判斷int型變量a是奇數仍是偶數ide

a&1 == 0 偶數
a&1 == 1 奇數

2.求平均值,好比有兩個int類型變量x、y,首先要求x+y的和,再除以2,可是有可能x+y的結果會超過int的最大表示範圍。code

(x&y)+((x^y)>>1);
知識點:>>n 至關於除於2^n ,<<n 至關於乘於2^n 。
x,y對應位均爲1,相加後再除以2仍是原來的數,如兩個00001000相加後除以2仍得00001000,那麼咱們把x與y分別分紅兩個部分來看,二者相同的位分別拿出來 則 :
x = (111111111111000)2 =  (111111111111000)2 +  (000000000000000)2
y =  (111111111111010)2 =  (111111111111000)2 +  (000000000000010)2
相同部分咱們叫作x1,y1,不一樣部分咱們叫作x2,y2.那麼如今(x+y)/2 =(x1+y1)/2 +(x2 + y2)/2 ,由於x1 == y1 ,因此(x1+y1)/2 ==x1 ==y1,相同部分咱們用與運算求出來 x1 = x&y ,不一樣部分的和咱們用^求出來,而後除於2就是咱們想要的結果了。

3.對於一個大於0的整數,判斷它是否是2的幾回方對象

((x&(x-1))==0)&&(x!=0);
    /*若是是2的冪,n必定是100... n-1就是1111....
       因此作與運算結果爲0*/

4.好比有兩個int類型變量x、y,要求二者數字交換,位運算的實現方法支付寶

x ^= y;
    y ^= x;
    x ^= y;

5.求絕對值get

int abs( int x ) {
         int y ;
         y = x >> 31 ;
        return (x^y)-y ;        //or: (x+y)^y
   }

6.取模運算,採用位運算實現it

a % (2^n) 等價於 a & (2^n - 1) ;或者 m % n 等價於 m & (n-1)

7.乘法運算 採用位運算實現table

a * (2^n) 等價於 a << n

8.除法運算轉化成位運算

a / (2^n) 等價於 a>> n

9.求相反數

(~x+1)

10.a % 2 等價於

a & 1

11.取int型變量a的第k位 (k=0,1,2……sizeof(int))

a>>k&1   (先右移再與1)

12.將int型變量a的第k位清0

a&~(1<<k)    (10000 取反後爲00001 )

13.將int型變量a的第k位置1

a|(1<<k)

14.int型變量循環左移k次

a<<k|a>>16-k   (設sizeof(int)=16)

15.int型變量a循環右移k次

a>>k|a<<16-k   (設sizeof(int)=16)

16.對於一個數 x >= 0,判斷是否是2的冪。

boolean isPower2(int x) {
        return ((x&(x-1))==0) && (x!=0);
    }

17.不用temp交換兩個整數

void swap(int x , int y) {
        x ^= y;
        y ^= x;
        x ^= y;
    }

18.條件判斷賦值簡寫

if (x == a)
        x= b;
   else
        x= a;

  等價於 x= a ^ b ^ x;

19.x的相反數

(~x+1)

20.m乘以2的n次方

m << n

21.m除以以2的n次方

m >> n

22.求整數k從x位(高)到y位(低)間共有多少個1

public static int findChessNum(int x, int y, int k) {
  int result = 0;
  for (int i = y; i <= x; i++) {
    result += ((k >> (i - 1)) & 1);
  }
  return result;
  }

23.取絕對值

int abs(int n){
      return (n ^ (n >> 31)) - (n >> 31);
  }
/* n>>31 取得n的符號,若n爲正數,n>>31等於0,若n爲負數,n>>31等於-1
若n爲正數 n^0=0,數不變,若n爲負數有n^-1 須要計算n和-1的補碼,而後進行異或運算, 結果n變號而且爲n的絕對值減1,再減去-1就是絕對值 */

24.只出現一次的數字
給定一個非空整數數組,除了某個元素只出現一次之外,其他每一個元素均出現兩次。找出那個只出現了一次的元素。
說明:你的算法應該具備線性時間複雜度。 你能夠不使用額外空間來實現嗎?
示例 1:

輸入: [2,2,1]輸出: 1

示例 2:

輸入: [4,1,2,1,2]輸出: 4

這個題首先想到的就是異或的特性。相同的數字異或的結果爲 0,那麼出現奇數次的必定就是最後咱們想要的結果。

public int singleNum(int[] nums){
    int res = num[0];
    for(int i=1;i<nums.length;i++){
        res ^= nums[i];
    }
    return res;
}

總結

功能 示例 位運算
去掉最後一位 (101101->10110) x >> 1
在最後加一個0 (101101->1011010) x < < 1
在最後加一個1 (101101->1011011) x < < 1+1
把最後一位變成1 (101100->101101) x | 1
把最後一位變成0 (101101->101100) x | 1-1
最後一位取反 (101101->101100) x ^ 1
把右數第k位變成1 (101001->101101,k=3) x | (1 < < (k-1))
把右數第k位變成0 (101101->101001,k=3) x & ~ (1 < < (k-1))
右數第k位取反 (101001->101101,k=3) x ^ (1 < < (k-1))
取末三位 (1101101->101) x & 7
取末k位 (1101101->1101,k=5) x & ((1 < < k)-1)
取右數第k位 (1101101->1,k=4) x >> (k-1) & 1
把末k位變成1 (101001->101111,k=4) x | (1 < < k-1)
末k位取反 (101001->100110,k=4) x ^ (1 < < k-1)
把右邊連續的1變成0 (100101111->100100000) x & (x+1)
把右起第一個0變成1 (100101111->100111111) x | (x+1)
把右邊連續的0變成1 (11011000->11011111) x | (x-1)
取右邊連續的1 (100101111->1111) (x ^ (x+1)) >> 1
去掉右起第一個1的左邊 (100101000->1000) x & (x ^ (x-1))
判斷奇數 (x&1)==1
判斷偶數 (x&1)==0

點擊閱讀更多,查看更多詳情

相關文章
相關標籤/搜索