您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關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是奇數還是偶數
a&1 == 0 偶數 a&1 == 1 奇數
2.求平均值,比如有兩個int類型變量x、y,首先要求x+y的和,再除以2,但是有可能x+y的結果會超過int的最大表示范圍。
(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.求絕對值
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) ;或者 m % n 等價于 m & (n-1)
7.乘法運算 采用位運算實現
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 |
感謝各位的閱讀!關于“Java位運算的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。