簡介
位運算符用來對二進制位進行操作,Java中提供了如下表所示的位運算符:位運算符中,除 ~ 以外,其餘均為二元運算符。
運算元只能為整型和字元型數據。
3.4.1補碼
Java使用補碼來表示二進制數,在補碼錶示中,最高位為符號位,正數的符號位為0,負數為1。補碼的規定如下:
對正數來說,最高位為0,其餘各位代表數值本身(以二進制表示),如+42的補碼為00101010。
對負數而言,把該數絕對值的補碼按位取反,然後對整個數加1,即得該數的補碼。如-42的補碼為11010110(00101010按位取反11010101+1=11010110)
用補碼來表示數,0的補碼是唯一的,都為00000000。(而在原碼,反碼錶示中,+0和-0的表示是不唯一的,可參見相應的書籍)。而且可以用111111表示-1的補碼(這也是補碼與原碼和反碼的區別)。
3.4.2按位取反運算符~
~ 是一元運算法,對數據的每個二進制位取反,即把1變為0,把0變為1。
例如:
0010101
~
1101010
注意,~運算符與-運算符不同,~21≠-21。
3.4.3按位與運算符&
參與運算的兩個值,如果兩個相應位都為1,則該位的結果為1,否則為0。即:
0&0=0,0&1=0,1&0=0,1&1=1
C語言的六種位運算符
按位與運算
按位與運算符"&"是雙目運算符。 其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1 ,否則為0。參與運算的數以補碼方式出現。
例如:9&5可寫算式如下: 00001001 (9的二進制補碼)&00000101 (5的二進制補碼) 00000001 (1的二進制補碼)可見9&5=1。 按位與運算通常用來對某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 運算 ( 255 的二進制數為11111111)。
按位或運算
按位或運算符“|”是雙目運算符。 其功能是參與運算的兩數各對應的二進位相或。只要對應的二個二進位有一個為1時,結果位就為1。參與運算的兩個數均以補碼出現。
例如:
可寫算式如下:
(十進制為13)可見9|5=13
按位異或運算
按位異或運算符“^”是雙目運算符。 其功能是參與運算的兩數各對應的二進位相異或,當兩對應的二進位相異時,結果為1。
參與運算數仍以補碼出現。
例如
可寫成算式如下:
(十進制為12)
求反運算
求反運算符~為單目運算符,具有右結合性。 其功能是對參與運算的數的各二進位按位求反。
例如
的運算為:
結果為:
左移運算
左移運算符“<<”是雙目運算符。左移n位就是乘以2的n次方。 其功能把“<<”左邊的運算數的各二進位全部左移若干位,由“<<”右邊的數指定移動的位數,高位丟棄,低位補0。
1)例: a<<4 指把a的各二進位向左移動4位。如a=00000011(十進制3),左移4位後為00110000(十進制48)。
2)例: int i = 1; i = i << 2; //把i里的值左移2位 也就是說,1的2進制是000...0001(這裡1前面0的個數和int的位數有關,32位機器,gcc里有31個0),左移2位之後變成 000...0100,也就是10進制的4,所以說左移1位相當於乘以2,那么左移n位就是乘以2的n次方了(有符號數不完全適用,因為左移有可能導致符號變化,下面解釋原因)
需要注意的一個問題是:int類型最左端的符號位和移位移出去的情況. 我們知道,int是有符號的整形數,最左端的1位是符號位,即0正1負,那么移位的時候就會出現溢出, 例如: int i = 0x40000000; //16進制的40000000,為2進制的01000000...0000 i = i << 1; 那么,i在左移1位之後就會變成0x80000000,也就是2進制的100000...0000,符號位被置1,其他位全是0,變成了int類型所能表示的最小值,32位的int這個值是,溢出.如果再接著把i左移1位會出現什麼情況呢?
在C語言中採用了丟棄最高位的處理方法,丟棄了1之後,i的值變成了0. 左移里一個比較特殊的情況是當左移的位數超過該數值類型的最大位數時,編譯器會用左移的位數去模類型的最大位數,然後按餘數進行移位,如: int i = 1, j = 0x80000000; //設int為32位 i = i << 33; // 33 % 32 = 1 左移1位,i變成2 j = j << 33; // 33 % 32 = 1 左移1位,j變成0,最高位被丟棄 在用gcc編譯這段程式的時候編譯器會給出一個warning,說左移位數>=類型長度.那么實際上i,j移動的就是1位,也就是33%32後的餘數.在gcc下是這個規則,不同編譯器可能會不完全相同.
總之左移就是: 丟棄最高位,0補最低位
右移運算
右移運算符“>>”是雙目運算符。右移n位就是除以2的n次方
其功能是把“>>”左邊的運算數的各二進位全部右移若干位,“>>”右邊的數指定移動的位數。
例如:設 a=15,a>>2 表示把00001111右移為00000011(十進制3)。 應該說明的是,對於有符號數,在右移時,符號位將隨同移動。當為正數時, 最高位補0,而為負數時,符號位為1,最高位是補0或是補1 取決於編譯系統的規定。Turbo C和很多系統規定為補1。
右移對符號位的處理和左移不同: 對於有符號整數來說,比如int類型,右移會保持符號位不變,
例如: int i = 0x80000000; i = i >> 1; //i的值不會變成0x40000000,而會變成0xc0000000 就是說,對於有符號數, 符號位向右移動後,正數的話補0,負數補1, 對於有符號數,在右移時,符號位將隨同移動: 當為正數時, 最高位補0, 而為負數時,符號位為1, 也就是彙編語言中的算術右移.同樣當移動的位數超過類型的長度時,會取餘數,然後移動餘數個位. 最高位是補0或是補1 取決於編譯系統的規定。Turbo C和很多系統規定為補1。 負數10100110 >>5(假設字長為8位),則得到的是 11111101 總之,在C中,左移是邏輯/算術左移(兩者完全相同),右移是算術右移,會保持符號位不變.實際套用中可以根據情況用左/右移做快速的乘/除運算,這樣會比循環效
率高很多.
以此類推. 無符號:
請再看一例!
異或操作的妙用
1. 使特定位翻轉 要使哪幾位翻轉就將與其進行∧運算的該幾位置為1即可。
2 與0相∧,保留原值.
3.交換兩個值,不用臨時變數. 我們可以在不用引入其他變數就可以實現變數值的交換 用異或操作可以實現: a = a^b; //
(1) b = a^b; //
(2) a = a^b; //
(3) 異或操作滿足結合律和交換律,且由異或操作的性質知道,對於任意一個整數a^a=0; 證:(第(2)步中的a) a = a^b =(將第(1)步中的b代入b) a^(a^b) = b; (第(3)步中的b)b =a^b = (將第(1)步中的b代入b,將第(2)步中的a代入a) a^b^a^a^b = a^a^a^b^b = a;
位與運算
清零 A數中為1的位,B中相應位為0。然後使二者進行&運算,即可達到對A清零目的。
取一個數中某些指定位 取數A的某些位,把數B的某些位置1,就把數A的某些位與1按位與即可。
保留一位的方法 數A與數B進行&運算,數B在數A要保留的位1,其餘位為零。
判斷奇偶性 將變數 a的奇偶性。a與1做位與運算,若結果是1,則 a是奇數;將 a與1做位與運算,若結果是0,則 a是偶數。
套用舉例
判斷int型變數a是奇數還是偶數 a&1 = 0 偶數 a&1 = 1 奇數
取int型變數a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1
將int型變數a的第k位清0,即a=a&~(1<
將int型變數a的第k位置1, 即a=a|(1<
int型變數循環左移k次,即a=a<>16-k (設sizeof(int)=16)
int型變數a循環右移k次,即a=a>>k|a<<16-k (設sizeof(int)=16)
整數的平均值
對於兩個整數x,y,如果用 (x+y)/2 求平均值,會產生溢出,因為 x+y 可能會大於INT_MAX,但是我們知道它們的平均值是肯定不會緋齙模?頤怯萌縵濾惴ǎ?/DIV> int average(int x, int y) //返回X,Y 的平均值 { return (x&y)+((x^y)>>1); }
判斷一個整數是不是2的冪,對於一個數 x >= 0,判斷他是不是2的冪 boolean power2(int x) { return ((x&(x-1))==0)&&(x!=0); }
不用temp交換兩個整數 void swap(int x , int y) { x ^= y; y ^= x; x ^= y; } php: $a ="dd"; $b = 'bb'; $a = $a ^ $b; $b = $a ^ $b;
$a = $a ^ $b; echo $a,' ', $b; 10 計算絕對值 int abs( int x ) { int y ; y = x >> 31 ; return (x^y)-y ; //or: (x+y)^y }
取模運算轉化成位運算 (在不產生溢出的情況下) a % (2^n) 等價於 a & (2^n - 1) 12 乘法運算轉化成位運算 (在不產生溢出的情況下) a * (2^n) 等價於 a<< n 13. 除法運算轉化成位運算 (在不產生溢出的情況下) a / (2^n) 等價於 a>> n 例: 12/8 == 12>>3 14 . a % 2 等價於 a & 1 15 if (x == a) x= b; else x= a; 等價於 x= a ^ b ^ x;
16 x 的 相反數 表示為 (~x+1)abc
php位運算符
位運算符允許對整型數中指定的位進行置位。如果左右參數都是字元串,則位運算符將操作字元的 ASCII 值。