表4.2 位運算符及其結果
運算符 結果
~ 按位非(NOT)(一元運算)
& 按位與(AND)
按位或(OR)
^ 按位異或(XOR)
>> 右移
>>> 右移,左邊空出的位以0填充
運算符 結果
<< 左移
&= 按位與賦值
= 按位或賦值
^= 按位異或賦值
>>= 右移賦值
>>>= 右移賦值,左邊空出的位以0填充
<<= 左移賦值
續表
既然位運算符在整數范圍內對位操作,因此理解這樣的操作會對一個值產生什么效果是重要的。具體地說,知道Java 是如何存儲整數值并且如何表示負數的是有用的。因此,在繼續討論之前,讓我們簡短概述一下這兩個話題。
所有的整數類型以二進制數字位的變化及其寬度來表示。例如,byte 型值42的二進制代碼是00101010 ,其中每個位置在此代表2的次方,在最右邊的位以20開始。向左下一個位置將是21,或2,依次向左是22,或4,然后是8,16,32等等,依此類推。因此42在其位置1,3,5的值為1(從右邊以0開始數);這樣42是21+23+25的和,也即是2+8+32 。
所有的整數類型(除了char 類型之外)都是有符號的整數。這意味著他們既能表示正數,又能表示負數。Java 使用大家知道的2的補碼(two's complement )這種編碼來表示負數,也就是通過將與其對應的正數的二進制代碼取反(即將1變成0,將0變成1),然后對其結果加1。例如,-42就是通過將42的二進制代碼的各個位取反,即對00101010 取反得到11010101 ,然后再加1,得到11010110 ,即-42 。要對一個負數解碼,首先對其所有的位取反,然后加1。例如-42,或11010110 取反后為00101001 ,或41,然后加1,這樣就得到了42。
假如考慮到零的交叉(zero crossing )問題,你就輕易理解Java (以及其他絕大多數語言)這樣用2的補碼的原因。假定byte 類型的值零用00000000 代表。它的補碼是僅僅將它的每一位取反,即生成11111111 ,它代表負零。但問題是負零在整數數學中是無效的。為了解決負零的問題,在使用2的補碼代表負數的值時,對其值加1。即負零11111111 加1后為100000000 。但這樣使1位太靠左而不適合返回到byte 類型的值,因此人們規定,-0和0的表示方法一樣,-1的解碼為11111111 。盡管我們在這個例子使用了byte 類型的值,但同樣的基本的原則也適用于所有Java 的整數類型。
因為Java 使用2的補碼來存儲負數,并且因為Java 中的所有整數都是有符號的,這樣應用位運算符可以輕易地達到意想不到的結果。例如,不管你如何打算,Java 用高位來代表負數。為避免這個討厭的意外,請記住不管高位的順序如何,它決定一個整數的符號。
4.2.1 位邏輯運算符
位邏輯運算符有“與”(AND)、“或”(OR)、“異或(XOR )”、“非(NOT)”,分別用“&”、“”、“^”、“~”表示,4-3 表顯示了每個位邏輯運算的結果。在繼續討論之前,請記住位運算符應用于每個運算數內的每個單獨的位。
表4-3 位邏輯運算符的結果
A 0 1 0 1 B 0 0 1 1 A B 0 1 1 1 A & B 0 0 0 1 A ^ B 0 1 1 0 ~A 1 0 1 0
按位非(NOT)
按位非也叫做補,一元運算符NOT“~”是對其運算數的每一位取反。例如,數字42,它的二進制代碼為:
00101010
經過按位非運算成為
11010101
按位與(AND)
按位與運算符“&”,假如兩個運算數都是1,則結果為1。其他情況下,結果均為零。看下面的例子:
00101010 42 &00001111 15
00001010 10
按位或(OR)
按位或運算符“”,任何一個運算數為1,則結果為1。如下面的例子所示:
00101010 42 00001111 15
00101111 47
按位異或(XOR)
|
新聞熱點
疑難解答