在計算機中全部數據都是以二進制的形式儲存的。位運算其實就是直接對在內存中的二進制數據進行操做,所以處理數據的速度很是快。在正式介紹位運算以前咱們先補充幾個概念,若是已經熟悉的讀者能夠忽略。bash
符號位: 二進制數最高位表示符號位,0表示正數,1表示負數。
原碼: 整數的二進制數。
反碼: 符號位不變,其他部分取反。
補碼: 原碼取反+1,符號位不變。或者說反碼+1,符號位不變。
負數的原碼即爲:正數的原碼取反,再加1,即正數的補碼就是負數的原碼。markdown
好比11和-11
11的原碼:00000000 00000000 00000000 00001011
11的反碼:01111111 11111111 11111111 11110100
11的補碼:01111111 11111111 11111111 11110101spa
-11的原碼:11111111 11111111 11111111 11110101code
1.按位操做符
2.移位操做符orm
按位操做符用來操做整數基本數據類型中的單個「比特(bit)」,即二進制。按位操做符會對兩個參數中的位執行布爾代數運算,並最終生成一個結果。對象
1.按位「與」操做符(&)內存
解釋:對兩個整數的二進制形式逐位進行邏輯與運算編譯器
若是兩個輸入位都是1,那麼按位「與」(&)操做就會生成一個輸出位1,不然生成一個輸出位0。it
1&1=1; 1&0=0; 4&-5=0;
複製代碼
4&-5分析:io
4的二進制:00000000 00000000 00000000 00000100
-5的二進制:11111111 11111111 11111111 11111011
因此4&-5的二進制爲 00000000 00000000 00000000 00000000
轉換爲10進製爲0。
因此4&-5=0;
2.按位「或」操做符(|)
解釋:對兩個整數的二進制形式逐位進行邏輯或運算。
若是兩個輸入位都是1,那麼按位「或」(|)操做符生成一個輸出位1,只有兩個輸入位都是0的狀況下,纔會生成一個輸出位0。
1|0=1;
0|0=0;
4|-5=-1;
複製代碼
一樣以4|-5爲例:
4|-5:
4的二進制:00000000 00000000 00000000 00000100,
-5的二進制:11111111 11111111 11111111 11111011,
逐位進行邏輯或運算:11111111 11111111 11111111 11111111,即獲得-1.
3.按位「異或」操做符(^)
解釋:對兩個整數的二進制形式逐位進行邏輯異或運算。
若是輸入位的某一個是1,但不全都是1,那麼按位「異或」(^)操做,生成一個輸出位1。
1^1=0; 1^0=1; 0^0=0; 4^-5=-1;
複製代碼
4^-5:
4的二進制:00000000 00000000 00000000 00000100,
-5的二進制:11111111 11111111 11111111 11111011,
逐位進行邏輯異或運算:11111111 11111111 11111111 11111111,即獲得-1.
4.按位非(~)
解釋:對兩個整數的二進制形式逐位進行取反。
按位非(~)操做符,也稱爲取反操做符。它屬於一元操做符,只對一個數進行操做(其餘按位操做符是二元操做符),按位「非」生成與輸入位相反的值,若輸入0,則輸出1;若輸入1,則輸出0。
~4=-5;
複製代碼
4的二進制形:00000000 00000000 00000000 00000100,逐位取反後得11111111 11111111 11111111 11111011,即爲-5。
移位操做符操做的運算對象也是二進制的「位」。移位操做符只能用來處理整數類型。移位操做符分爲:1.左移位操做符(<<),2.「有符號」右移位操做符(>>),3.「無符號」右移操做符(>>>)。
1.左移位操做符(<<)
例如:4<<2
4的二進制形式: 00000000 00000000 00000000 00000100,進行左位移2位,獲得00000000 00000000 00000000 00010000,即爲16.
10737418<<8
10737418二進制表示形式:00000000 10100011 11010111 00001010,進行左位移2位,獲得10100011 11010111 00001010 00000000,即爲:-1546188288.
2.有符號右位移操做符(>>)
m>>n的含義: 把整數m表示的二進制數右移n位,m爲正數,高位所有補0;m爲負數,高位所有補1。
例如 4>>2
4的二進制形式: 00000000 00000000 00000000 00000100,進行右位移2位,獲得00000000 00000000 00000000 00000000,即爲1.
-4>>2剖析:
-4二進制形式: 11111111111111111111111111111100,右移2位,獲得11111111 11111111 11111111 11111111,即爲-1.
PS: 每一個整數表示的二進制都是32位的,若是右移32位和右移0位的效果是同樣的。依次類推,右移32的倍數位都同樣。至關於總體全移。與移0位相同。左移也是同樣的。
3.無符號右移操做符(>>>)
m>>>n: 整數m表示的二進制右移n位,不論正負數,高位都補零。
例如: 4>>>2:
4二進制形式: 00000000 00000000 00000000 00000100,右移兩位,獲得00000000 00000000 00000000 00000001,即爲1。
-4>>>2:
-4二進制形式: 11111111111111111111111111111100,右移兩位,獲得00111111 11111111 11111111 11111111,即爲1073741823.
補充
對於移位操做符若是n爲負數:這時JVM會先讓n對32取模,變成一個絕對值小於32的負數,而後再加上32,直到 n 變成一個正數。
例如:
4<<-10
4的二進制形式:00000000 00000000 00000000 00000100,-10對32取模再加上32,不用說了,獲得22,則4<<-10,即至關於4<<22。
此時按照再左移22位,獲得00000001 00000000 00000000 00000000,獲得的即爲:16777216。
4.其餘非整型數值位移處理
若是對char,byte或者short類型的數值進行位移處理,那麼在移位以前會,它們會被轉爲int類型,而且獲得的結果也是int類型的值。只有數值有段的低5位纔有用。這樣能夠防止咱們移位超過int型所具備的位數。(2的5次方等於32,int只有32位)。
「移位」能夠與「等號」(<<=或>>=或>>>=組合使用)。此時,操做符左邊的值會移動指定的位數,而後將結果複製給左邊的變量。但在進行「無符號」右移位集合結合賦值操做時,會出現一個問題:若是對byte或short值進行這樣的移位運算,獲得的可能不是正確的結果。它們會先被轉成int類型,而後進行右移操做,而後被截斷,再賦值給原來的類型。
例如:
public static void main(String [] args)
{
byte a;
byte b;
byte c;
a = 127;
b = 127;
c = 127;
a <<= 2;
System.out.println(a);
System.out.println(b <<= 2);
System.out.println(c << 2);
}
複製代碼
輸出的結果爲 -4 -4 508 這說明了在操做a <<= 2 執行過程是這樣的:先將 byte型的數 127變成int型,左移2位獲得 508,而後把508賦給byte型變量a時只是簡單地」折斷」(truncate)獲得數-4。編譯時編譯器不會提示你可能損失精度(實際上在本例中確實是損失精度了)。