溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java位運算的示例分析

發(fā)布時間:2022-01-05 16:15:52 來源:億速云 閱讀:204 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關(guān)Java位運算的示例分析的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

位運算表達式由操作數(shù)和位運算符組成,實現(xiàn)對整數(shù)類型的二進制數(shù)進行位運算。位運算符可以分為邏輯運算符(包括~、&、|和^)及移位運算符(包括>>、<<和>>>)。

1)左移位運算符(<<)能將運算符左邊的運算對象向左移動運算符右側(cè)指定的位數(shù)(在低位補0)。
2)“有符號”右移位運算符(>>)則將運算符左邊的運算對象向右移動運算符右側(cè)指定的位數(shù)。 “有符號”右移位運算符使用了“符號擴展”:若值為正,則在高位插入0;若值為負,則在高位插入1。
3)Java也添加了一種“無符號”右移位運算符(>>>),它使用了“零擴展”:無論正負,都在高位插入0。這一運算符是C或C++沒有的。
4)若對char,byte或者short進行移位處理,那么在移位進行之前,它們會自動轉(zhuǎn)換成一個int。 只有右側(cè)的5個低位才會用到。這樣可防止我們在一個int數(shù)里移動不切實際的位數(shù)。 若對一個long值進行處理,最后得到的結(jié)果也是long。此時只會用到右側(cè)的6個低位,防止移動超過long值里現(xiàn)成的位數(shù)。 但在進行“無符號”右移位時,也可能遇到一個問題。若對byte或short值進行右移位運算,得到的可能不是正確的結(jié)果(Java 1.0和Java 1.1特別突出)。 它們會自動轉(zhuǎn)換成int類型,并進行右移位。但“零擴展”不會發(fā)生,所以在那些情況下會得到-1的結(jié)果。

在進行位運算時,需要注意幾點:

(1)>>>和>>的區(qū)別是:在執(zhí)行運算時,>>>運算符的操作數(shù)高位補0,而>>運算符的操作數(shù)高位移入原來高位的值。
(2)右移一位相當(dāng)于除以2,左移一位(在不溢出的情況下)相當(dāng)于乘以2;移位運算速度高于乘除運算。
(3)若進行位邏輯運算的兩個操作數(shù)的數(shù)據(jù)長度不相同,則返回值應(yīng)該是數(shù)據(jù)長度較長的數(shù)據(jù)類型。
(4)按位異或可以不使用臨時變量完成兩個值的交換,也可以使某個整型數(shù)的特定位的值翻轉(zhuǎn)。
(5)按位與運算可以用來屏蔽特定的位,也可以用來取某個數(shù)型數(shù)中某些特定的位。
(6)按位或運算可以用來對某個整型數(shù)的特定位的值置1。

位運算符的優(yōu)先級

~的優(yōu)先級最高,其次是<<、>>和>>>,再次是&,然后是^,優(yōu)先級最低的是|。

位運算的應(yīng)用

1.判斷int型變量a是奇數(shù)還是偶數(shù)

a&1 == 0 偶數(shù)
a&1 == 1 奇數(shù)

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

  (x&y)+((x^y)>>1);
知識點:>>n 相當(dāng)于除于2^n ,<<n 相當(dāng)于乘于2^n 。
x,y對應(yīng)位均為1,相加后再除以2還是原來的數(shù),如兩個00001000相加后除以2仍得00001000,那么我們把x與y分別分成兩個部分來看,兩者相同的位分別拿出來 則 :
x = (111111111111000)2 =  (111111111111000)2 +  (000000000000000)2
y =  (111111111111010)2 =  (111111111111000)2 +  (000000000000010)2
相同部分我們叫做x1,y1,不同部分我們叫做x2,y2.那么現(xiàn)在(x+y)/2 =(x1+y1)/2 +(x2 + y2)/2 ,因為x1 == y1 ,所以(x1+y1)/2 ==x1 ==y1,相同部分我們用與運算求出來 x1 = x&y ,不同部分的和我們用^求出來,然后除于2就是我們想要的結(jié)果了。

3.對于一個大于0的整數(shù),判斷它是不是2的幾次方

((x&(x-1))==0)&&(x!=0);
    /*如果是2的冪,n一定是100... n-1就是1111....
       所以做與運算結(jié)果為0*/

4.比如有兩個int類型變量x、y,要求兩者數(shù)字交換,位運算的實現(xiàn)方法

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.取模運算,采用位運算實現(xiàn)

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

7.乘法運算 采用位運算實現(xiàn)

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

8.除法運算轉(zhuǎn)化成位運算

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

9.求相反數(shù)

  (~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型變量循環(huán)左移k次

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

15.int型變量a循環(huán)右移k次

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

16.對于一個數(shù) x >= 0,判斷是不是2的冪。

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

17.不用temp交換兩個整數(shù)

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的相反數(shù)

  (~x+1)

20.m乘以2的n次方

  m << n

21.m除以以2的n次方

  m >> n

22.求整數(shù)k從x位(高)到y(tǒng)位(低)間共有多少個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為正數(shù),n>>31等于0,若n為負數(shù),n>>31等于-1
若n為正數(shù) n^0=0,數(shù)不變,若n為負數(shù)有n^-1 需要計算n和-1的補碼,然后進行異或運算, 結(jié)果n變號并且為n的絕對值減1,再減去-1就是絕對值 */

24.只出現(xiàn)一次的數(shù)字
給定一個非空整數(shù)數(shù)組,除了某個元素只出現(xiàn)一次以外,其余每個元素均出現(xiàn)兩次。找出那個只出現(xiàn)了一次的元素。
說明:你的算法應(yīng)該具有線性時間復(fù)雜度。 你可以不使用額外空間來實現(xiàn)嗎?
示例 1:

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

示例 2:

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

這個題首先想到的就是異或的特性。相同的數(shù)字異或的結(jié)果為 0,那么出現(xiàn)奇數(shù)次的一定就是最后我們想要的結(jié)果。

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

總結(jié)

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

感謝各位的閱讀!關(guān)于“Java位運算的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI