1. 程式人生 > >原碼,反碼,補碼,左移,右移

原碼,反碼,補碼,左移,右移

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]