【引自黑馬王子的部落格】Java中的位操作指定包括:<br />~ 按位非(NOT)<br />& 按位與(AND)<br />| 按位或(OR)<br />^ 按位異或(XOR)<br />>> 右移<br />>>> 無符號右移<br /><<左移<br />前面幾個都非常簡單,主要是移位操作比較容易出錯.<br />首先要搞清楚參與運算的數的位元,如int的是32位。long的是64位。<br />如int i = 1;<br />i的二進位原碼錶示為:<br />00000000000000000000000000000001<br />long l = 1;<br />l的二進位原碼錶示為:<br />0000000000000000000000000000000000000000000000000000000000000001<br />二、 </p><p>正數沒有反碼、補碼,也可以說正數的反碼、補碼跟原碼一樣。<br />負數的反碼為原碼逐位取反,<br />如int i = -1;<br />10000000000000000000000000000001,最高位是符號位。正數為0,負數為1。<br />逐位取反後:<br />01111111111111111111111111111110即反碼。<br />反碼加1:<br />01111111111111111111111111111111即補碼。<br />負數都是用補碼參與運算的。得到的也是補碼,需要減1取反獲得原碼。</p><p>三、常用的位元運算符--0在位元運算中是比較特殊的。 </p><p>^ 異或。 相同為0,相異為1; 任何數與0異或都等於原值。 <br />& 與。 全1為1, 有0為0;任何數與0異或都等於0。<br />| 或。 有1為1, 全0為0。任何數與0或都等於原值。<br /><<左移。 補0。<br />>> 右移。 符號位是0補0,是1補1。<br />>>>無符號右移。補0。<br />~ 非 逐位取反 </p><p>四、負數參與的運算,得到的是補碼,需要將補碼先減1,然後逐位取反,得到原碼。即為運算結果。 </p><p>0例外,如果得到的是0,則不需減1和取反。<br />另外,兩個正數運算後得到的就是原碼,不需減1和取反。<br />舉例:<br />1^-1,<br />-1<br />10000000000000000000000000000001--原碼<br />01111111111111111111111111111110--反碼<br />01111111111111111111111111111111--補碼<br />1<br />00000000000000000000000000000001--原碼<br />則1^-1等於<br />01111111111111111111111111111111^<br />00000000000000000000000000000001=<br />01111111111111111111111111111110--補碼<br />01111111111111111111111111111101--反碼<br />10000000000000000000000000000010--原碼==-2<br />即1^-1=-2<br />舉例:<br />1^-2<br />-2<br />10000000000000000000000000000010--原碼<br />01111111111111111111111111111101--反碼<br />01111111111111111111111111111110--補碼<br />1<br />00000000000000000000000000000001--原碼<br />則1^-2等於<br />01111111111111111111111111111110^<br />00000000000000000000000000000001=<br />01111111111111111111111111111111--補碼<br />01111111111111111111111111111110--反碼<br />10000000000000000000000000000001--原碼==-1<br />1.<<<br />邏輯左移,右邊補0,符號位和其他位一樣.<br />正數:<br />x<<1一般相當於2x,但是可能溢出.<br />溢出範圍: 230~(231-1) 二進位表示 010000...000到01111....1111,移位後最高為變為1了,變成負數了.<br />負數:<br />x<<1一般也相當於2x,也有可能溢出.所以, x*32可以寫成x<<5<br />溢出範圍: -231~-(230+1)二進位表示10000...000到101111...1111,移位後最高為變成0了,變成正數了.<br />2.>><br />算術右移,和上面的不對應,為正數時左邊補0,為負數時左邊補1.<br />x>>1,相當於x/2,餘數被捨棄,因為這個是縮小,所以不會溢出.<br />不過有一點要注意: -1右移多少位都是-1.<br />另外捨棄的餘數是正的, 3>>1=1 捨棄的餘數是1.<br />-3>>1=-2 捨棄的餘數也是1,而不是-1.<br />對於正數 x>>1和x/2相等<br />對於負數 x>>1和x/2不一定相等.<br />3.>>><br />邏輯右移,這個才是和<<對應的<br />這個把符號位一起移動,左邊補0<br />對於正數,>>>和>>是一樣的<br />對於負數,右移之後就變成正數了.<br />可以使用Integer.toBinaryString(int i)來看01位元,更加直觀.<br />考慮下面的代碼:<br />for (val = 0; val < 100000; val +=5) { alterX = val * 8; myResult = val * 2; }<br />用移位操作替代乘法操作可以極大地提高效能。下面是修改後的代碼:<br />for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << 1; }<br />修改後的代碼不再做乘以8的操作,而是改用等價的左移3位操作,每左移1位相於乘以2。相應地,右移1位操作相當於除以2。值得一提的是,雖然移位操作速度快,但可能使代碼比較難於理解,所以最好加上一些注釋。 </p><p>無符號右移位操作符“>>>”在將bit串右移位時,從bit串的最左邊填充0,這和帶符號右移位操作符“>>”不同。“>>”在將bit串右移位時,從bit串的最左邊填充原來最左邊的位。也就是說,bit串原來最左邊的位是符號位,如果為1,則在帶符號右移時最左邊始終填充1;如果為0,則在帶符號右移時最左邊始終填充0。</p><p>移位操作符的例子見下表。</p><p>操作 結果 說明<br />00110010 << 2 11001000 右邊始終填充0<br />00110010 >> 2 00001100 結果一樣<br />00110010 >>> 2 00001100<br />10110010 >> 2 11101100 結果不同<br />10110010 >>> 2 00101100 </p><p>“按位與”操作符“&”對兩個bit串按位進行邏輯與,“按位或”操作符“|”對兩個bit串按位進行邏輯或,“按位異或”操作符“^”對兩個bit串按位進行異或操作。運算規則如下表所示。</p><p>按位與 按位或 按位異或<br />0 & 0 = 0 0 | 0 = 0 0 ^ 0 = 0<br />0 & 1 = 0 0 | 1 = 1 0 ^ 1 = 1<br />1 & 0 = 0 1 | 0 = 1 1 ^ 0 = 1<br />1 & 1 = 1 1 | 1 = 1 1 ^ 1 = 0 </p><p>