原碼 補碼 反碼總結

2021-10-10 12:19:12 字數 3698 閱讀 7579

前一段時間在做模型外殼提取程式時候,用到了補碼的知識,現在系統的總結下原碼、補碼、反碼的知識。

你可能注意到了我寫的順序是補碼在反碼前面,是的,補碼不是必須依賴於反碼才能得知的,但本文為了方便講解和容易理解仍然採用了先反碼再補碼的順序。

本文以1個位元組的儲存空間為例進行講解。

原碼比較簡單,最高位為符號位(1代表負數,0代表正數),其他位表示該數值的絕對值,例如,

對於1個位元組的儲存,1000 1101 代表-13,   0000 1101代表13。

計算機運算器中有加法運算器,而沒有減法運算器,那麼對於原碼情況,我們結合加法的場景進行分析,

13+2=15,即

0000 1101 + 0000 0010 = 0000 1111 = 15,沒問題,

2+3=5,即

0000 0010 + 0000 0011 = 0000 0101 = 5,也沒問題,

2 + -1 = 1,即

0000 0010 + 1000 0001 = 1000 0011 = -3,?不對!

-2 + -1 = -3,即

1000 0010 + 1000 0001 = 0000 0011 = 3,?不對!

可以看出,對於正數加法沒問題(這也是後續要講的為什麼正數的反碼和補碼與原碼相同的原因之一),對於負數就有問題了。

那麼根據負數是其絕對值(正數)取反推出了反碼的概念。

正數的反碼和原碼相同,負數的反碼可以由原碼的符號位不變,其他位取反得來,仍以乙個位元組儲存為例,

十進位制數

原碼反碼

20000 0010

0000 0010

-31000 0011

1111 1100

對於正數反碼和原碼相同,

13+2=15,即

0000 1101 + 0000 0010 = 0000 1111 = 15,沒問題,

2+3=5,即

0000 0010 + 0000 0011 = 0000 0101 = 5,也沒問題,

2 + -1 = 1,即

0000 0010 + 1111 1110 = 0000 0000 = 0,?不對!

-2 + -1 = -3,即

1111 1101 + 1111 1110 = 1111 1011 = -4,?不對!

那麼再來看,

-2 + -3 = -5,即

1111 1101 + 1111 1100 = 1111 1001 = -6,?不對!

3 + -1 = 2,即

0000 0011 + 1111 1110 = 0000 0001 = 1,?不對!

-3 + 1 = -2,即

1111 1100 + 0000 0001 = 1000 0010 = -2,對了!

1 + -1 = 0,即

0000 0001 + 1111 1110 = 1111 1111 = -0,?也對,但為什麼不是0000 0000,這也是0(+0)啊,

可以看到,

對於正數相加,一如既往的沒問題;對於有負數的情況,有的就有問題了,有問題的好像都應該是結果+1後才是準確的,(二進位制計算-0+1=+0,即1111 1111 + 0000 0001 = 0000 0000)反正就是有點問題,

既然都引出反碼來了,好像離解決方案更進一步了,有規律了;那能不能引出個其他的什麼碼,對於正數來說這種碼和原碼相同(我們暫且稱之為解碼),

對於負數來說,解碼是其反碼+1,剛剛好能使負數參與的加法計算準確?

那麼到這裡你可能要說了,

上面-2 + -3 是兩個負數相加,如果每個負數都加1,那麼結果應該是在反碼運算結果:-2 + -3 = -6的基礎上進行修正(+1+1=+2),這樣不應該變成-4了嗎?

嗯,好問題,也比較嚴謹,-4是負值的解碼(反碼+1),其對應的反碼應相應的再-1,即反碼為-5,明白了沒?實質上還是反碼間的運算,只不過封裝了一層,便於計算。

上面-3 + 1 = -2 本來就正確了,如果每個負數都加1,那麼會出現什麼情況?(-3+1) + 1,相應的結果應該等於-2 + 1 = -1了,這不是又出錯了嗎?沒出錯,和上面一樣-1是是負值的解碼,其對應的反碼為-1-1=-2,依然正確,明白了沒?實質上就是反碼間的運算,只不過便於運算和理解又封裝了一層概念:解碼(暫時的名稱)。

上面3 + -1的情況又是怎樣的呢?3 + -1應該是2,但上述反碼計算後變為了1,不對了;在引入解碼後,3 + (-1 + 1)對應的結果為 1 + 1 = 2了,2也是解碼,正數的解碼等於其反碼,即結果轉換為反碼依然是2,沒問題,又印證了上述反覆陳述的論點:實質上就是反碼間的運算,只不過便於運算和理解又封裝了一層概念。

問題終結者來臨:真的有剛才的解碼嗎?有的,那就是 補碼,

正數的補碼和原碼相同,負數的補碼是其反碼+1,或者不依賴於反碼的解釋:負數的補碼等於其原碼自低位向高位遍歷,尾數的第乙個『1』及右邊的『0』保持不變,左邊的各位按位取反,符號位不變。

十進位制數

原碼反碼補碼2

0000 0010

0000 0010

0000 0010

-31000 0011

1111 1100

1111 1101

-0

1000 0000

1111 1111

0000 0000

0

0000 0000

0000 0000

0000 0000

???對於0的表示沒問題了?以前無論是原碼還是反碼都有+0和-0,甚至還有-0 + 1 = 0 的奇怪理論,補碼形式只有一種0,0就是0,沒有正負之分,或者稱其為正數。

趕快再分析下加法,驗證下上面關於分析反碼推出補碼可以解決負數參與的加法問題設想的正確性。

呼之欲出,

對於正數補碼和原碼相同,只有正數參與的加法一如既往的正確,不再贅述;下面分析負數參與的加法場景,

2 + -1 = 1,即

0000 0010 + 1111 1111 = 0000 0001 = 1,沒問題,

-2 + -1 = -3,即

1111 1110 + 1111 1111 = 1111 1101 = -3,沒問題,

那麼再來看,

3 + -1 = 2,即

0000 0011 + 1111 1111 = 0000 0010 = 2,沒問題,

1 + -1 = 0,即

0000 0001 + 1111 1111 = 0000 0000 = 0,沒問題,

為什麼補碼表示的數參與加法都沒問題?

這裡主要以負數為例,因為正數加法一如既往的簡單正確!

十進位制數

補碼-1

1111 1111

10000 0001

-21111 1110

20000 0010

看出規律了嗎?負數和其絕對值的二進位制相加等於

n + -1相當於n +(

這也是而其相應負數的補碼應該為

1000 0000 - 0000 0001 = 0111 1111 =

同時這也是為什麼有符號的乙個位元組能表示

想想,一天24小時,一年四季,一周七天,全球24個時區,六十一甲子,周而復始,減既是加,不扯了,你明白就行。

充分理解原碼、補碼和反碼的概念和這樣設計的緣由是很重要的,了解深層次原因可以加深理解,大道至簡,為了方便,為了高效。

參考

原碼 反碼 補碼的總結

原碼 反碼 補碼 數值在計算機中表示形式為機器數 計算機只能識別0和 1,使用的是二進位制 而在日常生活中人們使用的是十進位制 正如亞里斯多德早就指出的那樣 今天十進位制的廣泛採用 只不過我們絕大多數人生來具有 10個手指頭這個解剖學事實的結果 儘管在歷史上手指計數 5,10進製 的實踐要比二或三進...

原碼 反碼 補碼

正數 原碼 反碼 補碼一樣 7 原 0 0000111 b 7 反 0 0000111 b 7 補 0 0000111 b 負數 原碼就是原來的表示方法 反碼是除符號位 最高位 外取反 補碼 反碼 1 7 原 1 0000111 b 7 反 1 1111000 b 7 補 1 1111001 b 當...

原碼 反碼 補碼

正數 原碼 反碼 補碼一樣 7 原 0 0000111 b 7 反 0 0000111 b 7 補 0 0000111 b 負數 原碼就是原來的表示方法 反碼是除符號位 最高位 外取反 補碼 反碼 1 7 原 1 0000111 b 7 反 1 1111000 b 7 補 1 1111001 b 當...