技術點:
計算機中存儲是用補碼!!,同時注意一下計算省略了高位不變部分
1、byte:有符號(意思是有正和負),在網絡傳輸中都是會用到byte的,它佔1個字節,共8位,比如說11111111就可以用1個byte表示,轉化爲10進制:- (2的6次+2的5次+2的4次+2的3次+2的2次+2的1次+2的0次) = -127。其中前7位表示數字,最高位表示符號,0爲正,1爲負。範圍是 (-2的7次 ~ 2的7次 - 1),那爲什麼前面最小是-127,範圍最小又是-128呢?因爲規定-0(10000000)爲-128。
2、short:有符號,佔2個字節,共16位。同byte一樣,它的取值範圍就是 (-2的15次 ~ 2的15次 - 1)。
3、int :有符號,佔4個字節,共32位。它的取值範圍就是(-2的31次 ~ 2的31次)。
4、long:有符號,佔8個字節,共64位,它的取值範圍就是(-2的63次 ~ 2的63次)。
5、^:表示異或位運算,兩者相同則爲0,兩者不同則爲1。比如說15^2,15用二進制表示就是1111,2用2進製表示就是0010,兩者進行異或運算,結果就是1101,轉換爲十進制就是13。
A | B | A^B |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
6、|:表示或運算,兩者只有有一個爲1就爲1, 比如說13|2,13用二進制表示就是1101,2用二進制表示就是0010,兩者進行或運算,那麼結果就是1111,轉換爲十進制就是15。
A | B | A或B |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
7、&:表示與運算,兩者都爲1就爲1,其餘都爲0,比如說15&2, 13用二進制表示就是1111,2用二進制表示就是0010, 兩者進行與運算,那麼結果就是0010,轉換爲十進制就是2。
A | B | A&B |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
8、~:取反,就是本來是0變成1,本來是1變成0。
A | ~B |
---|---|
1 | 0 |
0 | 1 |
注意:本來我打算不想解釋這塊的,但是學知識,既然要學了,就儘自己最大努力一次性一個知識點學透徹。我舉個例子,比如說-15|3等於多少呢?有些人會覺得-15轉化爲二進制就是10001111,而3轉化爲二進制就是00000011,那麼結果應該是10001111呀,轉換爲十進制就是-15呀?大家可以自己寫個demo就會發現是不對的。要注意在計算機中所有的都是用補碼的形式存儲的,之所以上面介紹兩個正數是對的,因爲正數的反碼和補碼都是一樣的。而負數求補碼應該是出去符號位取反+1,我們再來看看這個題-15|3,其中-15的原碼爲10001111,反碼爲11110000,那麼補碼就是11110001,然後3的補碼爲00000011,兩者進行或操作就是11110011,你以爲結束了麼?還沒有,再又要求它的原碼了,原碼就是補碼再求補碼再+1(是不是已經暈掉了?),也就是10001101,結果就是-13。爲了大家都好理解,我這裏用算式整理一下:
求 -15|3
[-15]原碼 = 10001111
[-15]反碼 = 11110000 //原碼求反碼符號位不變
[-15]補碼 = 11110001 //反碼+1等於補碼
[3]原碼 = 00000011
[3]反碼 = 00000011 //正數都一致
[3]補碼 = 00000011 //正數都一致
-15|3 = 11110011 //兩個補碼進行或操作
[結果]補碼 = 11110011 //上面求得的值
[結果]反碼 = 10001100 //符號位不變
[結果]原碼 = 10001101 //反碼+1
100001101 轉化爲十進制就是-13。
不知道我這麼解釋會不會更加清楚一些呢?同理的,上面那些(尤其是求反‘~’我故意沒寫例子,大家自己去試試吧)。
在說一次,正數的原碼,補碼,反碼都一樣,如果一定要說爲什麼一樣,我就舉個例子。有這麼一個等式7+(-7)=0。
我們知道
[-7]原 = 10000111
[-7]反 = 11111000
[-7]補 = 11111001
那麼如果要存在一個值和[-7]補碼相加等於0,是不是就是00000111!!所以正數的補碼和原碼是一致的。這樣解釋雖然怪怪的,但是可以知道的確是這樣的。
9、<<:左移運算符,不需要考慮符號位,因爲在後面補0,把二進制的數字向左移動,低位補0。比如說 3<<2。3的二進制碼爲11,向左移動2位就是1100,那麼結果就是12。
10、>>:右移運算符,帶符號位。根據這個要移動的數字決定正負,如果是正數,那麼就在前面補0,如果是負數就在前面補1。比如說 3>>2,3的二進制碼爲00000011,向右移動2位,就變成00000000,轉化爲十進制就是0了(3是正數所以在高位補0)。再比如說-3>>2,-3的二進制碼爲10000011,轉化爲補碼(只要涉及到負數,就需要轉換到補碼計算,正數之所以不用轉化,是因爲他們的補碼和原碼是一致的)11111101,進行位移運算,就是11111111,這個是補碼,需要再轉回原碼。那麼就是取反+1,結果就是10000001,轉化爲十進制就是-1。
11、>>>:右移運算符,與上面的區別就是這個運算符是無符號的。不論正負,高位都補0。如果要用-3>>2來驗證,因爲高位補0,就需要把所有的位數都寫全了。如果是int,那就要寫成32位來運算。切記切記。上面很多因爲高位的變化“取反再取反”會導致前面所有的位都沒變所以我就簡化了,但是這個>>>運算符不行哦,它會把負數變爲正數。
代碼實現
基本步驟:
①分析轉化和代轉化之間位數的關係
②計算偏移量。每次都取最後8位
③把最後8位和0xff進行&操作
④得出結果。
有人會問,爲什麼要和0xff進行&操作?這裏我做一下解釋,因爲再在割的時候,我們要保證最後8位是一致的,更高位都要置0,這樣才能保證數據的一致性。比如說由byte轉化成short。位數從8位變成了16位,那麼在計算機自己看來,它會把前面多出來的8位置1。而&0xff就可以把前面所有的位數都置0。
1、short 與 byte互相轉化
public static byte[] short2byte(short s){
byte[] b = new byte[2];
for(int i = 0; i < 2; i++){
int offset = 16 - (i+1)*8; //因爲byte佔4個字節,所以要計算偏移量
b[i] = (byte)((s >> offset)&0xff); //把16位分爲2個8位進行分別存儲
}
return b;
}
public static short byte2short(byte[] b){
short l = 0;
for (int i = 0; i < 2; i++) {
l<<=8; //<<=和我們的 +=是一樣的,意思就是 l = l << 8
l |= (b[i] & 0xff); //和上面也是一樣的 l = l | (b[i]&0xff)
}
return l;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
2、int和byte的轉化也差不多
public static byte[] int2byte(int s){
byte[] b = new byte[2];
for(int i = 0; i < 4; i++){
int offset = 16 - (i+1)*8; //因爲byte佔4個字節,所以要計算偏移量
b[i] = (byte)((s >> offset)&0xff); //把32位分爲4個8位進行分別存儲
}
return b;
}
public static int byte2int(byte[] b){
int l = 0;
for (int i = 0; i < 4; i++) {
l<<=8; //<<=和我們的 +=是一樣的,意思就是 l = l << 8
l |= (b[i] & 0xff); //和上面也是一樣的 l = l | (b[i]&0xff)
}
return l;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
那麼long和byte的轉化,甚至是long和short等之間的轉化大家自己琢磨。看到這裏是不是覺得自己要學的東西很多,大學學過的都忘記了呢?沒關係,以後我會經常給大家複習一些重要但是不常用的東西哦。
轉發自:
https://blog.csdn.net/u012403290/article/details/68943827