一、什么是原碼、反碼和補碼
我們知道,在計算機內部存盤的帶符號數都是以補碼形式存盤,用補碼形式進行運算的,什么是一個數的補碼?為什么要用補碼?這要從數的原碼、反碼開始講,我們以整型數為例,且假定字長為8位,

1、原碼
整數X的原碼是指:其符號位為0表示正,為1表示負;其數值部分就是X的絕對值的二進制數,X的原碼通常用【X】原表示,如:
【+100】原=01100100 【+0】原=00000000
【-100】原=11100100 【-0】原=10000000
注意:在原碼中,零有兩種表示形式,
原碼表示法簡單易懂,與真值(帶符號數本身)轉換方便,只要符號還原即可,但當兩個正數相級訓不同符號數相加時,必須比較兩個數哪個絕對值大,才能決定誰減誰,才能確定結果是正還是負,所以原碼不便于加減運算,
2、反碼
X的反碼是指:對于正數,反碼與原碼相同;對于負數,符號位不變,其數值位X的絕對值取反(1變0,0變1),X的反碼通常用【X】反來表示,如
【+100】反=01100100 【+0】反=00000000
【-100】反=10011011【-0】反=11111111
注意:在反碼中,零也有兩種表示形式,
反碼運算也不方便,通常用來作為求補碼的中間過渡,
3、補碼
X的補碼是指:對于正數,補碼與原碼相同;對于負數,符號位不變,其數值位X的絕對值取反后在最低位加1,X的補碼通常用【X】補來表示,實際上,【X】補=【X】反+1,如:
【+100】補=01100100 【+0】補=00000000
【-100】補=10011100 【-0】補=00000000
注意:在補碼中,零有唯一的編碼,【+0】補=【-0】補=00000000,
補碼運算簡單方便,符號位可以作為資料的一位參與運算,不必單獨處理;二進制的減法可用其補碼的加法來實作,簡化了硬體電路,

二、補碼的意義
首先,我們來看幾個例子,
【例子1】用8位二進制數分別表示+0和-0 ,
解:我們知道,對于有符號數,我們規定最高位為符號位,0表示正數,1表示負數,剩余位為數值位,用來表示數的大小,
所以+0就表示為0000 0000,而-0表示為1000 0000,
【例子2】計算9-6的結果,
解:我們知道:9-6=9+(-6)=3
0000 1001
+1000 0110
1000 1111
結果為-15,明顯不對,
而如果我們采用補碼來進行計算呢?
我們知道,9的補碼是0000 1001,-6的補碼是11111010,重新進行運算,
0000 1001
+1111 1010
1 0000 0011
最高位的1溢位,剩余8位二進制表示的是3的補碼,結果為3,正確,
【例子3】分析程式運行結果,

main()
{int a=100,b=-1;
Printf(“a=%d,%x,%o,%u\n”,a,a,a,a);
Printf(“b=%d,%x,%o,%u\n”,b,b,b,b);}
運行結果:
a=100,64,144,100
b=-1,ffff,177777,65535
【例子1】中,為什么同樣一個0有兩種不同的表示方法呢?
【例子2】中,為什么第一種計算方法會錯,而用補碼計算結果才對呢?
而【例子3】中,為什么-1以十六進制、八進制以及無符號整型輸出的結果分別變成了ffff,177777,65535?
這是因為在計算機系統中,數值一律用補碼來表示(存盤),
主要原因:
1、統一了零的編碼;
2、將符號位和其它數值位統一處理;
3、將減法運算轉變為加法運算;
4、兩個用補碼表示的數相加時,如果最高位(符號位)有進位,則進位被舍棄,
三、補碼的計算
1、定義法:
(1)正數的補碼:與原碼相同,
【例1】+9的補碼是00001001,
(2)負數的補碼:符號位為1,其余位為該數絕對值的原碼按位取反;然后整個數加1,
【例2】求-9的補碼,
因為給定數是負數,則符號位為“1”,
后七位:+9的原碼(0001001)→按位取反(1110110)→加1(1110111)
所以-7的補碼是11110111,
2、查零法
原碼是用1來表示數值的大小,屬于正邏輯,對原碼的計算我們主要是計算1的個數;而反碼和補碼是用0來表示數值的大小,屬于負邏輯,所以我們可以采取 逆向邏輯思維來理解,通過計算0的個數來求負數的補碼,由于補碼是在反碼的基礎上加了一個1,所以0的個數應該比原數的絕對值小1,
例如:求-5的補碼
零的個數應為4個,所以-5的補碼為:11111011,
再如:求-97的補碼
零的個數應為96個,96=64+32,對應的權值位為0,其余位為1,所以-97的補碼為:10011111,
3、零減法
負數的補碼=全零-正數的原碼,如-5的補碼=0-5的原碼,
用該數的十六進制計算,得到的結果轉換為二進制即可,
例如:求-5的補碼
演算法1:演算法2:
00000000 00H
﹣00000101 ﹣05H
11111011 0 FBH
4、找1法
例如:求-15的補碼
第一步:+15:00001111
第二步:從右向左找到第一個1,然后把左邊的所有位取反,

如果你在學習C/C++的程序中遇到了問題,可以來加入小編的企鵝圈問小編哦~小編很熱情的(●’?’●)
11110001
再舉一個例子驗證下:求-64的補碼
+64:01000000
11000000
四、幾點補充
1、已知一個數的補碼,求原碼的操作分兩種情況:
(1)如果補碼的符號位為“0”,表示是一個正數,其原碼就是補碼,
(2)如果補碼的符號位為“1”,表示是一個負數,那么求給定的這個補碼的補碼就是要求的原碼,
【例3】已知一個補碼為11111001,則原碼是10000111(-7),
因為符號位為“1”,表示是一個負數,所以該位不變,仍為“1”,
其余七位1111001取反后為0000110;
再加1,所以是10000111,
2、數值范圍
8位二進制原碼所表示數的范圍是-127~+127;
五、總結:
1、原碼表示法
除了符號位外,其他二進制位為數值的絕對值,這種方案稱為“原碼”表示法,例如:
+20的原碼:0 000 0000 0001 0100
-20的原碼: 1 000 0000 0001 0100
2、反碼表示法
除了符號為以外,負數的反碼表示是在原碼的基礎上其他二進制取反,而正數的反碼表示與原碼相同,如:
+20的反碼為: 0 000 0000 0001 0100
-20的反碼為: 1 111 1111 1110 1011
3、補碼表示法
負數的補碼表示是在反碼基礎上加1,而正數的反碼表示與原碼相同,
4、為什么計算機一般采用補碼表示法
原碼、反碼和補碼是由于表示負數的三種方案,三種方案中,原碼最適合與乘除類運算,補碼適合于加減類運算,而反碼則加減與乘除都不是很理想,由于加減運算的頻率遠高于乘除運算,所以多數計算機系統采用的是補碼方案,所以所有計算機的加減運算都要將相應的數轉換成補碼,然后再進行運算,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/207122.html
標籤:其他
下一篇:小議緩沖區溢位
