補碼原理


補碼

所有的計算機資料都規定:補碼是將各位按位取反,再加1.

學的時候並沒有覺得有什么疑問,但是寫代碼很多年之后,回過頭去溫習計算機原理,突然冒出來幾個問題

為什么要有補碼這個東西?為什么補碼要按位取反?為什么要有左移右移?

這些都是為了計算機實現加減乘除才出現的。首先講講加減,計算機沒有減法,所以就是加上負數來替代它。

舉個例子吧
2的二進制是0000 0010,那么-2的表示是否是1000 0010呢
驗證一下,假如它們成立就必須2+(-2)=0
兩者的相加為1000 0100,不管前面符號位是0還是1,這個數都不等於0.

那么我們反過來想,我想要獲取一個數的負數是多少,那么只要確保這個數加上它的負數等於0

還是剛剛的例子
2的二進制是0000 0010,那么0的二進制是0000 0000
我們知道二進制加法中,正常情況下2加上任何數都不能等於0,只有一種情況,那就是高位溢出。比如2加上某個數變成了1 0000 0000,這個時候計算機會棄掉高位的1.
這就很簡單了,我把2按位取反,變成1111 1101,它加上2就是1111 1111,這個時候我只需要再加1,就能變成1 0000 0000.
所以將2按位取反再加1為 1111 1110,這就是補碼。

補碼的規則就有了,將各位按位取反,再加1. 補碼就是用正數表示的負數形式。

因為符號位的特殊,0000 0000 - 1111 1111 一共能表示256個,所以1個字節表示的無符號范圍是0 到28 -1(一共256個),有符號- 27 到 27-1(一共256個)

好,問題來了,無符號的范圍不用說,有符號的范圍為什么負數是-128,正數只能到127呢

我們可以看到,有符號位的二進制數第一位是符號,所以剩下的7位表示數
正數范圍從0到127沒有問題。
1到127對應的數都有其補碼,對應了-127到-1
唯獨剩下個0,0歸為正數,它的二進制是0000 0000,那么現在就剩下一個1000 0000沒有表示,因為符號位的原因,它相當於是-0.但是-0也是0,所以規定1000 0000表示負數最大值,也就是128

所以0的補碼就是-128,所以有符號位的范圍是-128到127

左移和右移

補碼的出現是為了表示負數,來做加法和減法。那么左移和右移就是來做乘法以及除法。

左移是指把所有的位向左移動n位數,那么這個數就擴大了2n

左移是指把所有的位向又移動n位數,那么這個數就縮小了2n

這樣我們就能實現乘法和除法,比如5*3就變成了5*(2+1)就等於5*21+5,也就是將5左移1位,再加上5。

除法假如除數是2的冪次方,比較簡單,右移2的冪次位就行,比如5/2,只要把5右移1位得到整數位是2.

那么小數位呢?(小數位比較復雜,這邊就不討論了)假如除數不是2的冪次方呢?

x/y其實就是,x不斷減y的過程。小學時候學的長長除法就是這個原理。
用二進制的除法x/y,比十進制容易寫,商不是0即是1,而且如果除數大於除數的1倍,商就是標記在另一個位上面了

二進制除法x/y=0.1001/0.1011手工計算如下
           0.11  
     _______
0.1001/0.1001
        10010(后面補0)
        -1011
      ------
        111(余數)
        1110(后面補0)
        -1011
       --------
             1(余數)
           
設ri表示第i次運算后所得的余數,則:
若ri>0,則商1,余數和商左移1位,再減去除數,即ri+1=2ri-y
若ri<0,則商0,余數和商左移1位,再加上除數,即ri+1=2ri+y

用85/6來舉例,85/6=1010101/110
a.101(0101)左移1位到第3位都小於110,因此商=000
b.1010(101)左移四位是1010,比110大,商=0001,余數=1010-110=100(101)
c.余數100(101)左移一位是1001,比110大,商=00011,余數=1001-110=11(01)
d.余數11(01)左移一位是110,等於110,商=000111,余數=0(1)
e.余數0(1)左移一位是01,小於110,商=0001110,余數=01

因此85/6=1010101/110=0001110,即14,余數為最后的余數1     

 

無符號數的左移和右移是沒有問題的,往左移相當於增加2倍,往右移是減小2倍,

但是假如是有符號數呢,第一位是符號位,那么直接把后面的7位左移或者右移就可以了嗎?

先來看左移

以-2為例
2轉換成二進制是0000 0010
2的補碼是 1111 1110
對1111 1110左移一位得到1111 1100
將補碼-1得到1111 1011,再按位取反得到正數是0000 0100,是4
左移1位相當於是乘以2

所以有符號數的左移也是相當於增加2的冪次方倍

下面看右移,這就涉及到2種方式:

 

 

邏輯右移:把所有的位,包括符號位向左或向右移動,高位補0

算術右移:假如是正數,高位補零,假如是負數,高位補1。

看圖中的例子,邏輯右移不能得到正確答案,算數右移才是正確的

還是以-4為例子, 我們先看下它的正數的例子
原始數值    0000 0100     
右移兩位    0000 0001
最終結果          1

我們還是按結果倒推,-4右移兩位我們想要的結果是-1
那么以-1為例,左移兩位不就是-4嗎
原始數值    1111 1111
左移兩位    1111 1100

根據補碼的規則,把正數的各位取反加1. 設想一下假如負數右移的過程中把高位取0,那么減去1之后,把各位再取反得到得正數,它得高位將會是1,這顯然是不對得。

所以負數得右移應該以算數右移為准。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM