什么是二進制
逢二進一的計數(shù)規(guī)則
2進制
規(guī)則:逢2進1
數(shù)字:0 1
權(quán):128 64 32 16 8 4 2 1
基數(shù):2
10進制
規(guī)則:逢10進1
數(shù)字:0 1 2 3 4 5 6 7 8 9
權(quán):萬 千 百 十 個
基數(shù):10
計算機為啥是2進制?便宜!成本優(yōu)勢明顯!
2進制數(shù):
/*如何查看整數(shù)的2進制存儲情況
* - java 編譯的時候,將數(shù)字編譯為2進制數(shù)字
* - 運行期間變量中存儲的是2進制數(shù)
* - 輸出變量的時候,Java利用API方法,將2進制轉(zhuǎn)換為10進制字符串
* - 利用valueOf方法轉(zhuǎn)換
*/
int n = 50; //110010
System.out.println(n); //利用valueOf轉(zhuǎn)換2進制為10進制字符串輸出
如何將2進制轉(zhuǎn)換為10進制:將1位置對應(yīng)權(quán)值累加求和
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001 = 1
00000000 00000000 00000000 00000010 = 2
00000000 00000000 00000000 00000011 = 2 + 1 = 3
00000000 00000000 00000000 00000100 = 4
00000000 00000000 00000000 00000101 = 4 + 1 = 5
00000000 00000000 00000000 00000110 = 4 + 2 = 6
00000000 00000000 00000000 00000111 = 4 + 2 + 1 = 7
.
.
.
.
00000000 00000000 00000000 00011001 = 16 + 8 + 1 = 25
00000000 00000000 00000000 01101000 = 64 + 32 + 16 + 8 = 25
什么是16進制
逢16進1的計數(shù)規(guī)則
16進制用途:16進制用于縮寫2進制
- 2進制書寫非常繁瑣
- 16進制的基數(shù)是2進制的基數(shù)4次方,2進制每4位數(shù)可以縮寫為1個16進制數(shù)
2進制與16進制
/*
* - java7 提供了2進制字面量前戳 0b
* 可以在數(shù)字中添加下劃線,不影響數(shù)值
* - 二進制直接書寫非常繁瑣
* - 16進制縮寫2進制就非常方便
* 從2進制的最低位開始,每4位*/
int a = 0b11_0010; //32+16+2 = 50;
a = 0b0001_1001_1111_0001_0100_0011_1111_0101; // 1_9_f_1_4_3_f_5
補碼
計算機中一種表示符號數(shù)編碼,其核心思想就是將固定位數(shù)2進制分一半作為負數(shù)
如何將固定位數(shù)2進制分一半作為負數(shù)?
- 以4位2進制數(shù)講解如何設(shè)計補碼
- 計算時保持4位不變,多余位自動溢出
- 最高位稱為符號位,
負數(shù)的編碼
-n = ~n+1 (min除外)
2進制運算
`~` 取反
`&` 與
`|` 或運算
`>>>` 右移位運算
`>>` 數(shù)學(xué)右移位運算
`<<` 左移位運算
&與運算
運算規(guī)則:邏輯乘法,有0則0
0 & 0 -> 0
0 & 1 -> 0
1 & 0 -> 0
1 & 1 -> 1
運算時,將兩個2進制數(shù)對位,對應(yīng)位置進行與運算
1 7 9 d 5 d 9 e
n = 00010111 10011101 01011101 10011110
m = 00000000 00000000 00000000 11111111 8位掩碼
k = n&m 00000000 00000000 00000000 10011110
如上運算的意義:k中存儲的是n的最后8位數(shù),叫掩碼(mask)運算。
m稱為mask(掩碼),一般從低位開始,1的個數(shù)稱為掩碼的位數(shù)。
int n = 0x179d5d9e;
/*4位掩碼:0xf 0b1111 15
* 6位掩碼:0x3f 0b111111 63
* 8為掩碼:0xff 0b11111111 255*/
int m = 0xff;
int k = n&m;
將一個整數(shù)拆分為4個字節(jié)
b1 b2 b3 b4
n = 00010111 10011101 01011101 10011110
b1 = 00000000 00000000 00000000 00010111
b2 = 00000000 00000000 00000000 10011101
b3 = 00000000 00000000 00000000 01011101
b4 = 00000000 00000000 00000000 10011110
int b1 = n>>>24;
int b2 = (n>>>16)&0xff;
int b3 = (n>>>8)&0xff;
int b4 = n&0xff;
>>>右移位運算
運算規(guī)則,將2進制整數(shù)整體向右移動,低位自動溢出舍棄,高位補0
n = 00010111 10011101 01011101 10011110
m=n>>>1 00001011 11001110 10101110 11001111
k=n>>>2 00000101 11100111 01010111 01100111
g=n>>>8 00000000 00010111 10011101 01011101
b3 = (n>>>8) & 0xff;
| 或運算
基本運算規(guī)則:邏輯加法,有1則1
0 | 0 -> 0
0 | 1 -> 1
1 | 0 -> 1
1 | 1 -> 1
運算時兩個2進制數(shù)對齊位,對應(yīng)位進行或運算
n = 00000000 00000000 00000000 11011101
m = 00000000 00000000 10011101 00000000
k = n|m 00000000 00000000 10011101 11011101
上述計算的意義:兩數(shù)錯位合并
int n = 0xdd;
int m = 0x9d00;
k=n|m; 0b_00000000_00000000_10011101_11011101
<< 左移位運算
2進制數(shù)字整體向左移動,高位自動溢出,低位補0
n = 00100000 11101111 00110101 10010000
m = n << 1 01000001 11011110 01101011 00100000
m = n << 2 10000011 10111100 11010110 01000000
g = n << 2 11101111 00110101 10010000 00000000
int n;
int b1 = 0x17;
int b2 = 0x9d;
int b3 = 0x5d;
int b4 = 0x9e;
n = (b1<<24)|(b2<<16)|(b3<<8)|b4; //n = 0x179d5d9e
移位運算的數(shù)學(xué)意義
16 8 4 2 1
1 0 1 = 5
1 0 1 0 = 10 向左移動1位 *2
1 0 1 0 0 = 20 向左移動1位 *2*2
int n = 5;
System.out.println(n<<1); //10
System.out.println(n<<2); //20
System.out.println(n<<3); //40
>>> 和 >> 的區(qū)別
-
>>>邏輯右移: 數(shù)字向右移動,低位自動溢出,高位補0,結(jié)果沒有數(shù)學(xué)意義。如果僅僅將數(shù)位向右移動,不考慮數(shù)學(xué)意義,則使用>>> -
>>數(shù)學(xué)右移位:數(shù)學(xué)向右移動,低位自動溢出,正數(shù)高位補0,負數(shù)高位補1,移動一次數(shù)學(xué)除以2,小方向取整數(shù)。如果是替代數(shù)學(xué)/2,使用數(shù)學(xué)右位移
n = 11111111 11111111 11111111 11001100 = -1-1-2-16-32 = -52
m=n>>1 11111111 11111111 11111111 11100110 = -1-1-8-16 = -26
k=n>>2 11111111 11111111 11111111 11110011 = -1-4-8= -13
g=n>>3 11111111 11111111 11111111 11111001 = -1-2-4= -7
n>>>1 01111111 11111111 11111111 11100110 = max - 25沒有數(shù)學(xué)意義