計(jì)算機(jī)和真實(shí)生活中不同,一個(gè)數(shù)在計(jì)算機(jī)中只能以二進(jìn)制(0或者1)的方式表示,現(xiàn)實(shí)生活中主要以十進(jìn)制表示,在二進(jìn)制的標(biāo)示中,最高位是符號(hào)位,最高位如果為0 ,則表示該數(shù)的十進(jìn)制表示為正數(shù),如果最高位為1,則該數(shù)位負(fù)數(shù)。以十進(jìn)制3為例,改為8位的二進(jìn)制,則是[0000 0011],如果是-3轉(zhuǎn)換為8位的二進(jìn)制是[1000 0011].在這里[0000 0011] 與3表示的意思相同 ,不過(guò)[0000 0011] 是機(jī)器數(shù),3為真值。
原碼, 反碼, 補(bǔ)碼的基礎(chǔ)概念
1. 原碼
原碼:是最簡(jiǎn)單的機(jī)器數(shù)表示法。用最高位表示符號(hào)位,‘1’表示負(fù)號(hào),‘0’表示正號(hào)。其他位存放該數(shù)的二進(jìn)制的絕對(duì)值。
若以1000? 0010 為例子
最高位為‘1’,表示這是一個(gè)負(fù)數(shù),其他七位為‘000? 0010’
即(0*2^7)+(0*2^6)+(0*2^5)+(0*2^4)+(0*2^3)+(0*2^2)+(1*2^1)+(0*2^0)=2(‘^’表示冪運(yùn)算符)
所以1000? 0010 是-2
2.反碼
反碼:正數(shù)的反碼還是等于原碼
負(fù)數(shù)的反碼就是他的原碼除符號(hào)位外,按位取反
若以帶符號(hào)位的八位二進(jìn)制數(shù)為例:
3是正數(shù),反碼與原碼相同,則可以表示為0000 0011
-3的原碼是1000 0011,符號(hào)位保持不變,低七位(000 0011)按位取反得(100? 1100)
3.補(bǔ)碼
補(bǔ)碼:正數(shù)的補(bǔ)碼等于他的原碼
負(fù)數(shù)的補(bǔ)碼等于反碼+1。
(這只是一種算補(bǔ)碼的方式,多數(shù)書(shū)對(duì)于補(bǔ)碼就是這句話)

前言
日常開(kāi)發(fā)中位運(yùn)算不是很常用,但是巧妙的使用位運(yùn)算可以大量減少運(yùn)行開(kāi)銷,優(yōu)化算法。舉個(gè)例子,翻轉(zhuǎn)操作比較常見(jiàn),比如初始值為1,操作一次變?yōu)?,再操作一次變?yōu)???赡艿淖龇ㄊ鞘褂萌具\(yùn)算符,判斷原始值為1還是0,如果是1,設(shè)置為0,否則設(shè)置為0.但是使用位運(yùn)算,不用判斷原始值,直接改變值就可以。當(dāng)然,一條語(yǔ)句可能對(duì)代碼沒(méi)什么影響,但是在高重復(fù),大數(shù)據(jù)量的情況下將會(huì)節(jié)省很多開(kāi)銷。
位運(yùn)算符
一些只需要一個(gè)操作數(shù)的運(yùn)算符稱為一元運(yùn)算符(或單目運(yùn)算符)。
二元運(yùn)算是由兩個(gè)元素形成第三個(gè)元素的一種規(guī)則。例如數(shù)的加法及乘法;更一般地,由兩個(gè)集合形成第三個(gè)集合的產(chǎn)生方法或構(gòu)成規(guī)則稱為二次運(yùn)算。(或雙目運(yùn)算符)
位邏輯運(yùn)算符
位邏輯運(yùn)算符包含 4 個(gè):&(與)、|(或)、~(非)和 ^(異或)。除了 ~(即位取反)為單目運(yùn)算符外,其余都為雙目運(yùn)算符。表 1 中列出了它們的基本用法。

位與運(yùn)算符
位與運(yùn)算符為&,其運(yùn)算規(guī)則是:參與運(yùn)算的數(shù)字,低位對(duì)齊,高位不足的補(bǔ)零,如果對(duì)應(yīng)的二進(jìn)制位同時(shí)為 1,那么計(jì)算結(jié)果才為 1,否則為 0。因此,任何數(shù)與 0 進(jìn)行按位與運(yùn)算,其結(jié)果都為 0。
例如下面的表達(dá)式:100&0
0110 0100? ---> 100
&0000 0000 --->? 0
? 0000 0000 --->? 0
代碼實(shí)現(xiàn):
? ? ? int x = 100,y = 0;
? ? ? int z = x&y;
? ? ? System.out.println("運(yùn)算結(jié)果:"+z);
//運(yùn)算結(jié)果:0
位或運(yùn)算符
位或運(yùn)算符為|,其運(yùn)算規(guī)則是:參與運(yùn)算的數(shù)字,低位對(duì)齊,高位不足的補(bǔ)零。如果對(duì)應(yīng)的二進(jìn)制位只要有一個(gè)為 1,那么結(jié)果就為 1;如果對(duì)應(yīng)的二進(jìn)制位都為 0,結(jié)果才為 0。
下面是一個(gè)使用位或運(yùn)算符的表達(dá)式:4|7
0000 0100--->4
|? ? 0000 0111--->7
? ? 0000 0111--->7
代碼驗(yàn)證:
? int x = 4,y = 7;
? ? ? int z = x|y;
? ? ? System.out.println("運(yùn)算結(jié)果:"+z);
//運(yùn)算結(jié)果:7
位異或運(yùn)算符
位異或運(yùn)算符為^,其運(yùn)算規(guī)則是:參與運(yùn)算的數(shù)字,低位對(duì)齊,高位不足的補(bǔ)零,如果對(duì)應(yīng)的二進(jìn)制位相同(同時(shí)為 0 或同時(shí)為 1)時(shí),結(jié)果為 0;如果對(duì)應(yīng)的二進(jìn)制位不相同,結(jié)果則為 1
下面是一個(gè)使用位異或運(yùn)算符的表達(dá)式:4^7
0000 0100--->4
^? 0000 0111--->7
? ? 0000 0011--->3
代碼驗(yàn)證:
? ? ? int x = 4,y = 7;
? ? ? int z = x^y;
? ? ? System.out.println("運(yùn)算結(jié)果:"+z);
//運(yùn)算結(jié)果:3
位取反運(yùn)算符
位取反運(yùn)算符為~,其運(yùn)算規(guī)則是:只對(duì)一個(gè)操作數(shù)進(jìn)行運(yùn)算,將操作數(shù)二進(jìn)制中的 1 改為 0,0 改為 1。
下面是一個(gè)使用位取反運(yùn)算符的表達(dá)式: ~5
位移運(yùn)算符
位移運(yùn)算符用來(lái)將操作數(shù)向某個(gè)方向(向左或者右)移動(dòng)指定的二進(jìn)制位數(shù)。表 2 列出了 Java 語(yǔ)言中的兩個(gè)位移運(yùn)算符,它們都屬于雙目運(yùn)算符。

左位移運(yùn)算符
左移位運(yùn)算符為?,其運(yùn)算規(guī)則是:按二進(jìn)制形式把所有的數(shù)字向左移動(dòng)對(duì)應(yīng)的位數(shù),高位移出(舍棄),低位的空位補(bǔ)零。
例如,將整數(shù) 7向左位移 1 位的過(guò)程如下:
? ? ? ? ? ? ? ? 0000 0111
? ? ? ? ? ? ? ? 00000 1110---->14
原來(lái)數(shù)的所有二進(jìn)制位都向左移動(dòng) 1 位。原來(lái)位于左邊的最高位 0 被移出舍棄,再向尾部追加 0 補(bǔ)位。最終到的結(jié)果是14,相當(dāng)于原來(lái)數(shù)的 2 倍。
代碼驗(yàn)證:
? ? ? int x = 7;
? ? ? int z = x <<1;
? ? ? System.out.println("運(yùn)算結(jié)果:"+z);
? ? ? //運(yùn)算結(jié)果:14
右位移運(yùn)算符
右位移運(yùn)算符為?,其運(yùn)算規(guī)則是:按二進(jìn)制形式把所有的數(shù)字向右移動(dòng)對(duì)應(yīng)的位數(shù),低位移出(舍棄),高位的空位補(bǔ)零。
例如,將整數(shù) 7向右位移 1 位的過(guò)程如下:
? ? ? ? ? ? ? ? ? ? ? ? 0000 0111
0000 00111---->3
原來(lái)數(shù)的所有二進(jìn)制位都向右移動(dòng) 1 位。原來(lái)位于右邊的最低位 1 被移出舍棄,再向最高位追加 0 補(bǔ)位。最終到的結(jié)果是 3,相當(dāng)于原數(shù)整除 2 余數(shù)舍棄的結(jié)果。
復(fù)合位賦值運(yùn)算符
所有的二進(jìn)制位運(yùn)算符都有一種將賦值與位運(yùn)算組合在一起的簡(jiǎn)寫形式。復(fù)合位賦值運(yùn)算符由賦值運(yùn)算符與位邏輯運(yùn)算符和位移運(yùn)算符組合而成。表 3 列出了組合后的復(fù)合位賦值運(yùn)算符。

? int a = 1;
? ? ? int b = 2;
? ? ? int c = 3;
? ? ? a &= 4;
? ? ? a |= 4;
? ? ? a ^= c;
? ? ? a -= 6;
? ? ? b >>= 1;
? ? ? c <<= 1;
? ? ? System.out.println("a = " + a);
? ? ? System.out.println("b = " + b);
? ? ? System.out.println("c = " + c);
????????a = 1
????????b = 1
????????c = 6