轉換:html
Java整型數據類型有:byte、char、short、int、long。要把它們轉換成二進制的原碼形式,必須明白他們各佔幾個字節。,一個字節==8位數web
數據類型 所佔位數
byte 8
boolean 8
short 16
int 32
long 64
float 32
double 64
char 16性能
byte
正數最大位0111 1111,也就是數字127
負數最大爲1111 1111,也就是數字-128
反碼與補碼
一、反碼:
一個數若是是正,則它的反碼與原碼相同;
一個數若是是負,則符號位爲1,其他各位是對原碼取反;
二、補碼:利用溢出,咱們能夠將減法變成加法
對於十進制數,從9獲得5可用減法:
9-4=5 由於4+6=10,咱們能夠將6做爲4的補數
改寫爲加法:
9+6=15(去掉高位1,也就是減10)獲得5.
對於十六進制數,從c到5可用減法:
c-7=5 由於7+9=16 將9做爲7的補數
改寫爲加法:
c+9=15(去掉高位1,也就是減16)獲得5.
在計算機中,若是咱們用1個字節表示一個數,一個字節有8位,超過8位就進1,在內存中狀況爲(100000000),進位1被丟棄。
⑴一個數爲正,則它的原碼、反碼、補碼相同
⑵一個數爲負,剛符號位爲1,其他各位是對原碼取反,而後整個數加1
詳細請參考http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html
Integer.toHexString的參數是int,若是不進行&0xff,那麼當一個byte會轉換成int時,因爲int是32位,而byte只有8位這時會進行補位,
例如補碼11111111的十進制數爲-1轉換爲int時變爲11111111111111111111111111111111好多1啊,即0xffffffff可是這個數是不對的,這種補位就會形成偏差。
和0xff相與後,高24比特就會被清0了,結果就對了。spa
還須要明白一點的是:計算機表示數字正負不是用+ -加減號來表示,而是用最高位數字來表示,0表示正,1表示負orm
在計算機系統中,數值一概用補碼來表示(存儲)。
主要緣由:使用補碼,能夠將符號位和其它位統一處理;同時,減法也可按加法來處理。另外,兩個用補
碼錶示的數相加時,若是最高位(符號位)有進位,則進位被捨棄。
補碼與原碼的轉換過程幾乎是相同的。
數值的補碼錶示也分兩種狀況:
(1)正數的補碼:與原碼相同。
例如,+9的補碼是00001001。
(2)負數的補碼:符號位(最高位)爲1,其他位爲該數絕對值的原碼按位取反;而後整個數加1。
例如,-7的補碼:由於是負數,則符號位爲「1」,整個爲10000111;其他7位爲-7的絕對值+7的原碼
0000111按位取反爲1111000;再加1,因此-7的補碼是11111001。
已知一個數的補碼,求原碼的操做分兩種狀況:
(1)若是補碼的符號位爲「0」,表示是一個正數,因此補碼就是該數的原碼。
(2)若是補碼的符號位爲「1」,表示是一個負數,求原碼的操做能夠是:符號位爲1,其他各位取反,而後再整個數加1。
例如,已知一個補碼爲11111001,則原碼是10000111(-7):由於符號位爲「1」,表示是一個負數,因此該位不變,仍爲「1」;其他7位1111001取反後爲0000110;再加1,因此是10000111。htm
源碼:是什麼就是什麼。負數就是最前面符號位爲1。
反碼:正的就是補碼,負的就是各位取反,0換1,1換0,注意,最高位符號爲不變。
補碼:正的就是源碼,負的就是反碼+1
好比: -1 -2
以8位二進制爲例
源碼:10000001 10000010
反碼:11111110 11111101
補碼:11111111 11111110
補碼這樣作的好處是什麼呢?
請看-1+(-2)電腦怎麼作:
用源碼:10000001 + (10000010)=00000011 這是什麼?是-3嗎?不是,是3。因此不能直接用源碼作加法。
用反碼:11111110 + (11111101)=11111011 這是什麼?是反碼的"-4"
用補碼:11111111 + (11111110)=11111101 末尾減一再取反得10000011,因此結果是補碼的-3。
反碼爲何出錯?以4位數爲例,高位爲符號位(括號內爲絕對值):
1010 (2)取反 1101 (5)
1011 (3)取反 1100 (4)
而後 -2 + (-3) 變成了 -(5 + 4)超出8的部分捨去,得 1001,再取反得 1110,成了-6
究其緣由:各位取反的兩數相加:1010+0101=1111必是全1即絕對值爲7,2->5,3->4,相對於8共誤差了2,而後9=1mod8,1->6,只修正了1點誤差,
結果就出現了1的誤差。補碼中末尾加一就是修正了該誤差,獲得正確的結果。即2->6,3->5.相對於8無誤差11=3mod8,3->5。blog
位運算符:內存
位移進制運算
帶符號右移 題:-15 >> 2 = -4
15原碼: 00000000 00000000 00000000 00001111 //32位,二進制
反碼: 11111111 11111111 11111111 11110000 //0變1,1變0
補碼: 11111111 11111111 11111111 11110001 //最後位加1,-15二進制
右移2位: 11111111 11111111 11111111 11111100 //右邊丟棄2位,前面30位保留,左邊補1
取反: 00000000 00000000 00000000 00000011 //0變1,1變0
+1: 3+1
結果: =-4 //負號保留,十進制
帶符號左移 題: 10 << 2 = 40
10 補碼: 00000000 00000000 00000000 00001010 //32位,二進制
左移2位: 00000000 00000000 00000000 00101000 //左邊丟棄2位,右邊補0
結果: 40 //十進制
無符號右移 題:-4321 >>> 30 = 3
4321原碼: 00000000 00000000 00010000 11100011 //32位,二進制
反碼: 11111111 11111111 11101111 00011100 //0變1,1變0
補碼: 11111111 11111111 11101111 00011101 //最後位加1,-4321二進制
無符號右移30位: 00000000 00000000 00000000 00000011 //右邊丟棄30位,前面二位保留,左邊補0
結果: 3 //十進制ci
& 位邏輯與 題:44 & 21 = 4
44 補碼: 00000000 00000000 00000000 00101100 //32位,二進制
21 補碼: 00000000 00000000 00000000 00010101 //32位,二進制
& 運算: 00000000 00000000 00000000 00000100 //對應的兩個二進制位均爲1時 結果位才爲1 不然爲0
結果: 4 //十進制
| 位邏輯與 題:9 | 5 = 13
9 補碼: 00000000 00000000 00000000 00001001 //32位,二進制
5 補碼: 00000000 00000000 00000000 00000101 //32位,二進制
| 運算: 00000000 00000000 00000000 00001101 //對應的二個二進制位有一個爲1時,結果位就爲1
結果: 13 //十進制
^ 位邏輯異或 題: 9 ^ 5 = 12
9 補碼: 00000000 00000000 00000000 00001001 //32位,二進制
5 補碼: 00000000 00000000 00000000 00000101 //32位,二進制
| 運算: 00000000 00000000 00000000 00001100 //對應的二進制位相異時,結果爲1
結果: 12 //十進制
~ 位邏輯反 題: ~9 = -10
9 補碼: 00000000 00000000 00000000 00001001 //32位,二進制
~ 運算: 11111111 11111111 11111111 11110110 //最高位爲1表示爲一個負數,則進行取反加1
取反: 00000000 00000000 00000000 00001001 //32位,二進制
+1: 9+1 //32位,二進制
結果: -10 //十進制源碼
因爲數據類型所佔字節是有限的,而位移的大小卻能夠任意大小,因此可能存在位移後超過了該數據類型的表示範圍,因而有了這樣的規定: 若是爲int數據類型,且位移位數大於32位,則首先把位移位數對32取模,否則位移超過總位數沒意義的。因此4>>32與4>>0是等價的。
若是爲long類型,且位移位數大於64位,則首先把位移位數對64取模,若沒超過64位則不用對位數取模。
若是爲byte、char、short,則會首先將他們擴充到32位,而後的規則就按照int類型來處理。
實際應用:
1. 判斷int型變量a是奇數仍是偶數
a&1 = 0 偶數
a&1 = 1 奇數
2. 求平均值,好比有兩個int類型變量x、y,首先要求x+y的和,再除以2,可是有可能x+y的結果會超過int的最大表示範圍,因此位運算就派上用場啦。
(x&y)+((x^y)>>1);
3. 對於一個大於0的整數,判斷它是否是2的幾回方
((x&(x-1))==0)&&(x!=0);
4. 好比有兩個int類型變量x、y,要求二者數字交換,位運算的實現方法:性能絕對高效
x ^= y;
y ^= x;
x ^= y;
5. 求絕對值
int abs( int x )
{
int y ;
y = x >> 31 ;
return (x^y)-y ; //or: (x+y)^y } 6. 取模運算,採用位運算實現: a % (2^n) 等價於 a & (2^n - 1) 7. 乘法運算 採用位運算實現 a * (2^n) 等價於 a << n 8. 除法運算轉化成位運算 a / (2^n) 等價於 a>> n 9. 求相反數 (~x+1) 10 a % 2 等價於 a & 1