原碼,反碼,補碼,左移,右移
1. 原碼
原碼就是符號位加上真值的絕對值,
即用第一位表示符號,其餘位表示值.
比如如果是8位二進位制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
第一位是符號位. 因為第一位是符號位, 所以8位二進位制數的取值範圍就是:
[1111 1111 , 0111 1111]
即
[-127 , 127]
2. 反碼
反碼的表示方法是:
正數的反碼是其本身
負數的反碼是在其原碼的基礎上, 符號位不變,其餘各個位取反.
[+1] = [0000 0001]原 = [0000 0001]反
[-1] = [1000 0001]原 = [1111 1110]反
3. 補碼
補碼的表示方法是:
正數的補碼就是其本身
負數的補碼是在其原碼的基礎上, 符號位不變, 其餘各位取反, 最後+1. (即在反碼的基礎上+1)
[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]補
[-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]補
4. 總結
在知道一個數原碼的情況下: 正數:反碼,補碼 就是本身自己 負數:反碼是高位符號位不變,其餘位取反。補碼:反碼+1 5. 左移當數值左、右移時,先將數值轉化為其補碼形式,移完後,再轉換成對應的原碼
左移:高位丟棄,低位補零
[+1] = [00000001]補
[0000 0001]補 << 1 = [0000 0010]補 = [0000 0010]原 = [+2]
[-1] = [1000 0001]原 = [1111 1111]補
[1111 1111]補 << 1 = [1111 1110]補 = [1000 0010]原 = [-2]
其中,再次提醒,負數的補碼是反碼+1;負數的反碼是補碼-1;
6.
右移
高位保持不變,低位丟棄
[+127] = [0111 1111]原 = [0111 1111]補
[0111 1111]補 >> 1 = [0011 1111]補 = [0011 1111]原 = [+63]
[-127] = [1111 1111]原 = [1000 0001]補
[1000 0001]補 >> 1 = [1100 0000]補 = [1100 0000]原 = [-64]
7.
總結
左移還是右移都先轉換成補碼形式
左移:高位丟棄,低位補零
右移:低位丟棄,高位不變
8.擴充套件
1、cout<<(unsigned)(~0)<<endl;
2、cout<<(int)(~0)<<endl;
上面的輸出是怎麼樣?
第一問:在32位機器上,[~0] = [1111 1111 .... 1111]原
計算機會將[1111 1111 .... 1111]看成補碼的形式,即 會輸出(unsigned)[1111 1111 .... 1111]補 對應的原碼 。
[1111 1111 .... 1111]補 轉化成 unsigned 型別 ,高位就不是符號位了,在32位機器,[1111 1111 .... 1111]對應的十進位制 。即 2^32 - 1 = 4294967295
第二問:會輸出(int)[1111 1111 .... 1111]補 對應的原碼 。此時,高位是符號位且是1,表示負,那麼
[1111 1111 .... 1111]補 = [1111 1111 .... 1110]反 = [1000 0000 .... 0001]原 = [-1]
3、cout<<unsigned(~1>>1)<<endl;
4、cout<<int(~1>>1)<<endl;
這又怎麼輸出呢?
首先做(~1>>1),再轉化成unsigned型別 或者 int型別
第三問:(~1>>1) = ~[0000 0000 .... 0001] >>1 = [1111 1111 .... 1110] >> 1
= [1111 1111 .... 1111]