1. 程式人生 > 其它 >關於計算機中使用補碼運算

關於計算機中使用補碼運算

1. 原碼、反碼、補碼簡單介紹

  • 原碼、反碼、補碼都是含有一個符號位的、對帶符號數的二進位制表示,對應於同一個真值。
  • 原碼帶符號位直接讀出來就是真值。
  • 正數三碼合一。
  • 負數的反碼為符號位不變(即保持為1),其餘位取反(相反轉換可用同樣方法);
  • 負數的補碼為符號位不變(即保持為1),其餘位取反後,對末位再加1(相反轉換可用同樣方法)。

  進一步理解:

  原碼:Sign-Magnitude。不妨以典型的8位二進位制為例(未做說明的話,下同),可以將8位劃分一個符號位和一個幅值區,幅值區為後7位。

  反碼:Ones' Complement。常說的通過取反操作獲得反碼的方式,本質上來源於1的補集。-X (X為正整數)的補碼,等於1111 1111減去X的8位2進位制的原碼錶示(注意,第一個1是符號位,可參與該處所作的相減運算。因為被減數是正整數的原碼,符號位為0,用1減去這個0,結果為1,所以不必僅令後7個1減去X的原碼的後7位、然後首位保持1,而可以直接全8位參與相減)。 如-3的補碼可這樣獲得:1111 1111 - 0000 0011 = 1111 1100,這和取反操作得到的結果是一致的(取反操作的話:原碼1000 0011→符號位保持1不變,其餘各位取反1111 1100)

  補碼:Two's complement。此處的two's指的是2^8,-X (X為正整數)的原碼,等於2^8減去X的8位2進位制的原碼錶示,也即1 0000 0000-減去X的8位2進位制的原碼錶示(注意2^8需用9位表示,且第一個1參與相減)。顯然2^8比1111 1111大1,這恰好和平時說的取反加1相一致(取反加1的說法可幫助到快速計算;2^8-X的說法有利於理解補碼運算是如何生效的 )。

2.補碼運算是如何生效的

  首先運算分三種:正數加正數;正數加負數;負數加負數(計算機只做加法,因為做減法的話,電子元件完成相應的物理實現需增加成本)。僅討論加數、被加數、減數、被減數的絕對值小於等於幅值區最大值的情形,如8位2進製表示法下的127。

  1. 正加正比較簡單,略去。

  2.正加負:為了方便,將前文所說的8位二進位制改作4位二進位制(含首位的符號位),此時0111=7即為所能表示的最大正數。

  結果為正的情況:以5-3為例,-3的補碼是 1 0000 - 0011 =1101,上述運算說明了:在1101的基礎上,再加3(即0011)即可滿模,即滿2^4=16=1 0000,從而使後4位清0。5-3相當於(-3)+5,加5過程中,加到3時已達成滿模清0,為完成加5操作,需繼續再加2,完成加2操作後,該加法運算便完成了,恰得到0010,即+2的補碼,便在計算機中完成了5-3=2的運算。

  結果為負的情況:以3-5為例。首先細述一遍運算過程:-5的補碼是 1 0000 - 0101 =1011,(-5)+3:1011 + 0011 = 1110,1110首位為1,為負數,其絕對值所對應的原碼為 1 0000 - 1110 = 0010,即絕對值為2,則1110對應於-2的補碼(上述運算過程中,已先求得了結果的補碼1110,在得到該補碼其對應原碼的過程中,使用了“1 0000 - 1110 = 0010”,這對應於從真值到補碼的逆運算,該運算式得到的是真值的絕對值,將0010的首位的0變為1,即得到了真值-2。實際上,若採用取反加1法的話,可以更快完成原碼和補碼的相互轉換:都是符號位不變(即保持為1),其餘位取反後,對末位再加1,而取反加1法對於相互轉換的有效性可以從上述運算過程中體會到)。考慮“-5的補碼是 1 0000 - 0101 =1011”,顯然,“1011”基礎上加3後所得到的補碼所對應的絕對值(因為只有負數的補碼是通過上式得到的,故僅適用於1011加3後的結果小於10000情況下,不然便對應於“結果為正的情況”了),可這樣得到:令“0101”減3,得到0010,即2,則結果為-2。

  “結果為正的情況”與“結果為負的情況”如何統一理解:B-A運算,總的來說,相當於用A在模(對於8位2進位制,為2^8=256)上挖個洞,然後用B去填。具體地,首先令模-A,得到了-A的補碼,其符號位為1。然後開始加B,(1)如果B小於A,那麼模無法填滿,-A的補碼加上B後,相加結果小於1 0000,即小於等於1111,符號位保持為1,仍保持為負數。但是相加運算使得模更接近於填滿,運算結果所對應的真值的絕對值更接近於0,負數沒那麼負了;且B越大,結果越沒那麼負,因為1 0000-(-A的補碼加上B)對應於結果的絕對值的真值,B越大,結果真值的絕對值便越小,同時考慮到結果為負數,所以說沒那麼負了;(2)如果B大於A,那麼模將填滿,-A的補碼加上B後,相加結果大於1 0000,即大於1111,滿模溢位,使得符號位由1變為0,從而使運算結果變為正數,此時B越大,運算結果所對應的真值作為一個正數其絕對值越大;(3)可以看到,利用補碼進行運算,並令符號位參與運算,能夠:滿模溢位時符號位變號,使得結果從負變為正;隨B的增大,運算結果的絕對值先減小再增大;這符合數學認知。

  3.負加負:1xxx + 1xxx的結果必然溢位,且結果是1 0xxx還是1 1xxx中的一種,前者表示無溢位,後者表示有溢位。至於計算機識別、處理溢位的細節和負加負運算的細節,沒弄明白,故不討論

3.利用原碼、反碼進行運算的劣勢

(此處圖片,擷取於參考資料1)

參考資料:

1. 為什麼計算機採用補碼而不是原碼或反碼? - 醉臥沙場的回答 - 知乎 https://www.zhihu.com/question/352057791/answer/876413629