原碼、反碼和補碼


在這篇博文中,我希望能從數學的角度幫助你理解計算機中的補碼世界,並嘗試解釋以下問題:

  • 符號位為什么是最高位,為什么1 表示負,0 表示正?0 表示正,1 表示負,為啥不是 0 表示負,1 表示正?

  • 為什么補碼 1000 0000 表示 -128 ?

  • 為什么補碼能夠實現減法運算?

關於原碼、反碼、補碼的計算這里就不贅述了,但是如果你對於原碼、反碼、補碼的計算還是通過一個數 -> 二進制原碼 -> 正數不變,負數保持符號位,其他位取反 得反碼 -> 反碼+1得補碼

另外也有上面的3個疑問的話

我強烈建議你忘掉之前關於原碼、反碼和補碼的認知

我首先拋出三個問題,希望你帶着這三個問題去閱讀,當你能給出這兩個問題的答案的時候,上面的3個問題也有答案了

  1. 同余的定義和意義是什么?
  2. 在4位系統中,怎么去表示負數?
  3. 在8位系統中,怎么做減法運算?

1. 環形系統、模、同余

在一個環形系統中,能表示的數是有限的。例如在下面的表盤中,你能表示的數只有0~11,大於等於12的數,會被舍棄一部分,再在表盤上表示出來,在計算機中,我們管這叫「溢出」。

比如15點,在鍾表上表現的是3。當表針越過11的時候,又從0開始,直到3。如果在鍾表的世界里,要表示27呢?鍾表上無法表示准確的數字,27在這里只能被表示為3。准確地說,在超出這個系統極限值的時候,也就是說溢出了,這個系統只能用「余數」來計量

在這里,所有被12除,余數為3的數,都被歸為1類。在這里,還有余數為0、1、2...11的類

而15和27,稱為 15和27關於模12同余,它們的余數就是3

在這個系統中,能表示的數只有「余數」,表盤上的數字都是被12除后的余數

我們可以這樣理解這個系統:這個系統將整數分成了12類——被12除余0、1、2、3、4、5、6、7、8、9、10、11的類

我們來看看「什么是奇數?什么是偶數?」

偶數是被2除余0的整數,奇數是被2除余1的整數。

通過模2我們將整數分成了兩類:余0和余1的數,也就是偶數和奇數

回到我們的表盤,通過模12,所有的整數也能被分成12類,分別是余0、1、2、3、4、5、6、7、8、9、10、11的類

所有的整數對模12做取模運算,按照它們的余數我們可以給它們分類。

\[1\ \text{mod} \ 12 = 1\\ 13\ \text{mod} \ 12 = 1\\ -11\ \text{mod} \ 12 = 1\\ -23\ \text{mod} \ 12 = 1\\ \]

1、13、-11、-23是同一類!

到這里,我們可以給出第一個問題的答案了。關於同余是這樣定義的:如果兩個數a、b除以模m,余數一樣,就稱整兩個數關於模m同余,記為

\[a \equiv b\ (\text{mod}\ m) \]

同余的意義就是分類!

2. 計算機世界

很容易理解計算機實際上就是一個環形系統。我們以4位bit來看看

在這個系統中,我們怎么表示負數呢?比如說 -2 ?既然這是一個環形系統,結合同余來看這個世界會變得極其容易。

根據同余-2 在這里和14 是同一類!所以我們可以用 14 的機器碼來表示 -2

14 的機器碼是 1110

現在問題出現了,1110 原來就是表示正數的14的,現在又要表示-2。那么當機器給我們這個二進制的時候,我們到底是把它看做14還是-2呢?

我們有一種做法:就是把0`15`個數分成了兩組,`0`7的機器碼還是代表原來的0`7`,`8`15的機器碼表示了-8~-1

當我們采用了上述這種分法的時候,歡迎來到補碼的世界。這正是我們現在的計算機世界——補碼世界

我們分別算一下-8~-1的關於模16的同余數以及同余數的二進制機器碼

這些表示是不是很熟悉?最高位的 1 表示號,補碼 1111 轉反碼 1110 轉原碼 1001 = -1。符號位 1 表示負數,0 表示正數,不是拍腦袋決定的,而是基於同余的思想

說到底,補碼的世界就是同余的世界啊!!!

到這里,我們可以解釋負數在4位系統中的表示了。通過引入了同余,將這個世界中一半的大數轉為了小數對應的負數

3. 8位系統中的減法運算

通過引入同余/補碼,我們可以表示負數,可以只用加法器實現減法運算

在這個補碼/同余的世界里,原生支持減法運算!!!

很容易得到,在8位系統中,mod = 1 0000 0000 = 256,負數的范圍是-128 ~ -1,正數是0 ~ 127

來看兩個例子:


「例子1」30 - 70 = ?

記住這是一個補碼的世界,我們沒必要管原碼和反碼,讓它們見鬼去吧!!!

30 的補碼是0001 1110,這個很順利,我們直接轉二進制就行了,因為 30 三 30 (mod 256)

-70 有點波折,因為我們需要知道它占用了哪個同余數的機器碼,256 - |-70| = 186。它占用了186 的機器碼,也就是 1011 1010

兩個機器碼直接相加得到 1101 1000。這是補碼!!直接轉是216。但是這個值大於127,我們知道這個數的機器碼被它的同余數-40 占用了

因為256 - |-40| = 216


「例子2」100 - 50 = ?

在這里,我們嘗試進入補碼世界,但是不用二進制表示,為了符合我們直觀

記住這是一個環形世界,306 在這個世界和 50 是一類。 306 三 50 (mod 256)50 的機器碼並沒有被占用,所以最終的答案就是 50


總結一下上面兩個例子,在8位系統中,模是256。能表示的數是 -128 ~ 127超出這個范圍的數都會根據同余被歸到其中的一類

為了說明補碼原生支持減法。我們想象一個8位系統,我們希望它能表示的數的范圍是 -100 ~ 155

現在計算 50 - 3030 - 50

看到了嗎?在這個補碼的世界里,才不管你是怎么分的,分成-128 ~ 127 也好,分成 -100 ~ 155 也罷,老子天然支持減法運算

4. 帶着補碼武功進入8位系統江湖中

為了幫助你融會貫通補碼這門武功,我決定帶着你闖盪一遍8位系統的江湖。在這里,不用管10,二進制也好,16進制也好,思想都是一樣的。

我們再來計算 109 - 99 - 109,記住,不要用 10 的機器碼,我們純用補碼的思想(也就是同余)來搞事

到了這里,是不是覺得補碼也就那么回事了。


現在,你是不是可以自己解決開篇的三個疑問了呢?帶着同余的思想去干掉這三個疑問吧!!


免責聲明!

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



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