前提都是8位的整數表示
-128沒有原碼和反碼(只有補碼)
那么,為什么規定字長8位時-128沒有原碼和反碼呢?下面解釋。
首先看-0,[-0]原碼=1000 000,其中1是符號位,求反操作,算出[-0]反碼=1111 1111,
再看-128,假如它有原碼且[-128]原碼=1000 0000,假如讓-128也有反碼,求反操作,則[-128]反碼=1111 1111,
你會發現,-128的反碼和-0的反碼相同,所以為了避免面混淆,有了-0的原碼,便不能有-128的原碼和反碼,這是8位比特位位數限制決定的。
直接復制一篇來吧
原文鏈接https://www.cnblogs.com/flowerslip/p/5933833.html
關於 -128 ,+128,-0,+0,-1 的反碼補碼
一.反碼的范圍
反碼表示法規定:正數的反碼與其原碼相同。負數的反碼是對其原碼逐位取反,但符號位除外。
在規定中,8位二進制碼能表示的反碼范圍是-127~127。
此時(字長為8位), -128沒有原碼和反碼(只有補碼)。
那么,為什么規定字長8位時-128沒有原碼和反碼呢?下面解釋。
首先看-0,[-0]原碼=1000 000,其中1是符號位,求反操作,算出[-0]反碼=1111 1111,
再看-128,假如它有原碼且[-128]原碼=1000 000,假如讓-128也有反碼,求反操作,則[-128]反碼=1111 1111,
你會發現,-128的反碼和-0的反碼相同,所以為了避免面混淆,有了-0的原碼,便不能有-128的原碼補碼,這是8位比特位位數限制決定的。
二.原碼 反碼 補碼的范圍
前提:字長是8位二進制數。
原碼 -127~127 -128呢???不是說-128有原碼 是1000 0000嗎??
反碼 -127~127
補碼 -128~127
對於n位二進制數:

你會發現,補碼比其它碼多一位,這是為什么呢?問題出在0上。
[+0]原碼=0000 0000, [-0]原碼=1000 0000
[+0]反碼=0000 0000, [-0]反碼=1111 1111
[+0]補碼=0000 0000, [-0]補碼=0000 0000
你會發現,+0和-0的補碼是一樣的。即 0的補碼只有一種表示。
這里解釋一下[-0]補碼是怎么得來的。
負數的補碼就是反碼整體加一。符號位上的進位舍棄。(所以,舍棄了符號位的補碼的第一位是數值位,不是符號位,符號位舍棄了)
另外解釋一下原碼符號位和補碼符號位的關系,補碼的符號位不是保持原碼的第一位不變,而是 符號位不變,[-0]反碼的第一個1是符號位,尾數中的7個1是數值位,尾數加一后,數值位產生了進位,1111 1111+1=1 0000 0000(計算補碼的過程中,並不是先保證第一位不變,而是保證符號位不變,保證補碼規則是反碼整體加一)。
所以,補碼能表示的數的個數中,比原碼反碼少了一個,所以補碼可以多表示一個真值為-128的數。
但是,多表示的這個數-128比較特殊,只有原碼和補碼,沒有反碼。
-128的補碼是1000 0000。
三.-128的補碼為什么是1000 0000
+128的原值在8位中是表達不出來的。
所以 256+(-128)的補碼=128
所以 (-128)的補碼=256-128
=128
數學上, 128=1000 0000
故規定-128的補碼為 1000 0000
0000 0000 - 0111 1111 0 ~+127
1000 0000 用來干啥好呢?
原碼 補碼 值
0111 1111 0111 1111 +127
0111 1110 0111 1110 +126
... .. 補碼不斷-1...
0000 0000 0000 0000 0
1000 0001 1111 1111 -1
1000 0010 1111 1110 -2
1000 0011 1111 1101 -3
... .. 補碼不斷-1...
1111 1111 1000 0001 -127
無法表達 1000 0000 -128
這種定法和上面數學層面的表述是一致的。
將該負數取絕對值,再用二進制表示出這個絕對值 (不管符號位!)
對該二進制數進行取反加一操作就得到負數的補碼了 (也就是求補操作!)
-128 絕對值是 128
128的二進制表示為:
1000 0000
取反
0111 1111
加1
1000 0000
這就是-128的補碼
這種辦法算出的結果符合“規定值”。
四.
1字節 = 8位,所以它能表示的最大數當然是8位都是1(既然2進制的數只能是0或1,如果是我們常見的10進制,那就8位都為9,這樣說,你該懂了?)
1字節的二進制數中,最大的數:11111111。
雙字節共16位。 1111111111111111。雙字節數最大值為:
1 * 215 + 1 *214 + 1* 213 + 1 * 212 + 1 * 211 + 1 * 210 + …… + 1 * 22 + 1 * 21 + 1* 20 = 65535
負數在計算機中如何表示呢?
這一點,你可能聽過兩種不同的回答。
一 種是教科書,它會告訴你:計算機用“補碼”表示負數。可是有關“補碼”的概念一說就得一節課,這一些我們需要在第6章中用一章的篇幅講2進制的一切。再 者,用“補碼”表示負數,其實是一種公式,公式的作用在於告訴你,想得到問題的答案,應該如何計算。卻並沒有告訴你為什么用這個公式就可以得到答案! -----我就是被這個弄混淆的>_<
另 一種是一些程序員告訴你的:用二進制數的最高位表示符號,最高位是0,表示正數,最高位是1,表示負數。這種說法本身沒錯,可是如果沒有下文,那么它就是 錯的。至少它不能解釋,為什么字符類型的-1用二進制表示是“1111 1111”(16進制為FF);而不是我們更能理解的“1000 0001”。(為什么說后者更好理解呢?因為既然說最高位是1時表示負數,那1000 0001不是正好是-1嗎?-----re!當初偶就是這么想的,so一直在腦中打架,越打越混淆=,=)。
讓我們從頭說起。
2.1、你自已決定是否需要有正負。
就像我們必須決定某個量使用整數還是實數,使用多大的范圍數一樣,我們必須自已決定某個量是否需要正負。如果這個量不會有負值,那么我們可以定它為帶正負的類型。
在計算機中,可以區分正負的類型,稱為有符類型,無正負的類型(只有正值),稱為無符類型。
數值類型分為整型或實型,其中整型又分為無符類型或有符類型,而實型則只有有符類型。
字符類型也分為有符和無符類型。
比如有兩個量,年齡和庫存,我們可以定前者為無符的字符類型,后者定為有符的整數類型。
3、無符號數和有符號數的范圍區別。
同樣是一個字節,無符號數的最大值是255,而有符號數的最大值是127。原因是有符號數中的最高位被挪去表示符號了。並且,我們知道,最高位的權值也是最高的(對於1字節數來說是2的7次方=128),所以僅僅少於一位,最大值一下子減半。
不過,有符號數的長處是它可以表示負數。因此,雖然它的在最大值縮水了,卻在負值的方向出現了伸展。我們仍一個字節的數值對比:
無符號數: 0 ----------------- 255
有符號數: -128 ----- 0 ----- 127
同樣是一個字節,無符號的最小值是 0 ,而有符號數的最小值是-128。所以二者能表達的不同的數值的個數都一樣是256個。只不過前者表達的是0到255這256個數,后者表達的是-128到+127這256個數。
一個有符號的數據類型的最小值是如何計算出來的呢?
有符號的數據類型的最大值的計算方法完全和無符號一樣,只不過它少了一個最高位(見第3點)。但在負值范圍內,數值的計算方法不能直接使用1* 26 + 1* 25 的公式進行轉換。在計算機中,負數除為最高位為1以外,還采用補碼形式進行表達。所以在計算其值前,需要對補碼進行還原。這里,先直觀地看一眼補碼的形式:
以我們原有的數學經驗,在10進制中:1 表示正1,而加上負號:-1 表示和1相對的負值。
那么,我們會很容易認為在2進制中(1個字節): 0000 0001 表示正1,則高位為1后:1000 0001應該表示-1。
然而,事實上計算機中的規定有些相反,請看下表:
| 二進制值(1字節) | 十進制值 |
| 1000 0000紅色的1代表負數藍色的是補碼(補碼=反碼+1) | -128 |
| 1000 0001藍色部分代表多大的值?:將補碼還原為原碼 | -127想化成負數?:先減去1再按位取反 |
| 1000 0010還原方法:補碼-1再取反 | -126 |
| 1000 0011 | -125 |
| ... | ... |
| 1111 1110 | -2 |
| 1111 1111 | -1 |
首先我們看到,從-1到-128,其二進制的最高位都是1(表中標為紅色),正如我們前面的學。
然后我們有些奇怪地發現,1000 0000 並沒有拿來表示 -0;而1000 0001也不是拿來直觀地表示-1。事實上,-1 用1111 1111來表示。
怎么理解這個問題呢?先得問一句是-1大還是-128大?
當 然是 -1 大。-1是最大的負整數。以此對應,計算機中無論是字符類型,或者是整數類型,也無論這個整數是幾個字節。它都用全1來表示 -1。比如一個字節的數值中:1111 1111表示-1,那么,1111 1111 - 1 是什么呢?和現實中的計算結果完全一致。1111 1111 - 1 = 1111 1110,而1111 1110就是-2。這樣一直減下去,當減到只剩最高位用於表示符號的1以外,其它低位全為0時,就是最小的負值了,在一字節中,最小的負值是1000 0000,也就是-128。
--------小米批注:就是這部分藍色的文字,讓我終於能記清楚-1的編碼方式了,汗=。=
我們以-1為例,來看看不同字節數的整數中,如何表達-1這個數:
| 字節數 | 二進制值 | 十進制值 |
| 單字節數 | 1111 1111紅色表示負數藍色部分的補碼為值1 | -1 |
| 負數:原碼就是原來的表示方法、反碼是除符號位(最高位)外取反、補碼=反碼+1雙字節數 | 1111 1111 1111 1111 | -1 |
| 四字節數 | 1111 1111 1111 1111 1111 1111 1111 1111 | -1 |
可 能有同學這時會混了:為什么 1111 1111 有時表示255,有時又表示-1?
所以我再強調一下本節前面所說的第2點:你自已決定一個數是有符號還是無符號的。寫程序時,指定一個量是有符號的,那么 當這個量的二進制各位上都是1時,它表示的數就是-1;相反,如果事先聲明這個量是無符號的,此時它表示的就是該量允許的最大值,對於一個字節的數來說, 最大值就是255。
ok 摘抄暫告段落,其實原文對於c的一些基礎數據類型知識介紹的非常詳細,8過太長了,摘到我需要的內容后就沒全帖過來,如果有需要學習的同學,建議參見原文:)
在計算機內部,所有信息都是用二進制數串的形式表示的。整數通常都有正負之分,計算機中的整數分為無符號的和帶符號的。無符號的整數用來表示0和正整數, 帶符號的證書可以表示所有的整數。由於計算機中符號和數字一樣,都必須用二進制數串來表示,因此,正負號也必須用0、1來表示。通常我們用最高的有效位來 表示數的符號(當用8位來表示一個整數時,第8位即為最高有效位,當用16位來表示一個整數時,第16位即為最高有效位。)0表示正號、1表示負號,這種 正負號數字化的機內表示形式就稱為“機器數”,而相應的機器外部用正負號表示的數稱為“真值”。將一個真值表示成二進制字串的機器數的過程就稱為編碼。
無符號數沒有原碼、反碼和補碼一說。只有帶符號數才存在不同的編碼方式。
帶符號整數有原碼、反碼、補碼等幾種編碼方式。原碼即直接將真值轉換為其相應的二進制形式,而反碼和補碼是對原碼進行某種轉換編碼方式。正整數的原 碼、反碼和補碼都一樣,負數的反碼是對原碼的除符號位外的其他位進行取反后的結果(取反即如果該位為0則變為1,而該位為1則變為0的操作)。而補碼是先 求原碼的反碼,然后在反碼的末尾位加1 后得到的結果,即補碼是反碼+1。IBM-PC中帶符號整數都采用補碼形式表示。(注意,只是帶符號的整數采用補碼存儲表示的,浮點數另有其存儲方式。)
采用補碼的原因或好處如下。
采用補碼運算具有如下兩個特征:
1)因為使用補碼可以將符號位和其他位統一處理,同時,減法也可以按加法來處理,即如果是補碼表示的數,不管是加減法都直接用加法運算即可實現。
2)兩個用補碼表示的數相加時,如果最高位(符號位)有進位,則進位被舍棄。
這樣的運算有兩個好處:
1)使符號位能與有效值部分一起參加運算,從而簡化運算規則。從而可以簡化運算器的結構,提高運算速度;(減法運算可以用加法運算表示出來。)
2)加法運算比減法運算更易於實現。使減法運算轉換為加法運算,進一步簡化運算器線路設計。
下面深入分析上面所陳述的采用補碼的原因(目的)。
用帶符號位的原碼進行乘除運算時結果正確,而在加減運算的時候就出現了問題,如下:假設字長為8bits
1 D- 1 D = 1 D + ( -1 )D = ( 0 )D
(00000001)原 + (10000001)原 = (10000010)原 = ( -2 ) 顯然不正確.。
因為在兩個整數的加法運算中是沒有問題的,於是就發現問題出現在帶符號位的負數身上,對除符號位外的其余各位逐位取反就產生了反碼。反碼的取值空間和原碼相同且一一對應。下面是反碼的減法運算:
1 D- 1 D = 1 D + ( -1 )D = ( 0 )D
(00000001) 反+ (11111110)反 = (11111111)反 = ( -0 ) 有問題。
1 D - 2 D= 1 D+ ( -2 )D = ( -1 )D
(00000001) 反+ (11111101)反 = (11111110)反 = ( -1 ) 正確
問題出現在(+0)和(-0)上,在人們的計算概念中零是沒有正負之分的。
於是就引入了補碼概念。負數的補碼就是對反碼加一,而正數不變,正數的原碼反碼補碼是一樣的。在補碼中用(-128)代替了(-0),所以補碼的表示范圍為:
(-128~0~127)共256個。
采用補碼表示還有另外一個原因,那就是為了防止0的機器數有兩個編碼。原碼和反碼表示的0有兩種形式+0和-0,而我們知道,+0和-0是相同的。這 樣,8位的原碼和反碼表示的整數的范圍就是-127~+127(11111111~01111111),而采用補碼表示的時候,00000000是+0, 即0;10000000不再是-0,而是-128,這樣,補碼表示的數的范圍就是-128~+127了,不但增加了一個數得表示范圍,而且還保證了0編碼 的唯一性。
接下來的問題是,如何能將減法運算轉換成加法運算呢?
我們已經知道,原碼表示簡單直觀,與真值轉換容易。但如果用原碼表示,其符號位不能參加運算。在計算機中用原碼實現算術運算時,要取絕對值參加運算,符號位單獨處理,這對乘除運算是很容易實現的,但對加減運算是非常不方便的,如兩個異號數相加,實際是要做減法,而兩個異號數相減,實際是要做加法。在做減法時,還要判斷操作數絕對值的大小,這些都會使運算器的設計變得很復雜。而補碼這種編碼方式實際上正是針對上述問題的。通過用補碼進行表示,就可以把減法運算化為加法運算。
在日常生活中,有許多化減為加的例子。例如,時鍾是逢12進位,12點也可看作0點。當將時針從10點調整到5點時有以下兩種方法:
一種方法是時針逆時針方向撥5格,相當於做減法:
10-5=5
另一種方法是時針順時針方向撥7格,相當於做加法:
10+7=12+5=5 (MOD 12)
這是由於時鍾以12 為模,在這個前提下,當和超過12時,可將12舍去。於是,減5相當於加7。同理,減4可表示成加8,減3可表示成加9,…。
在數學中,用“同余”概念描述上述關系,即兩整數A、B用同一個正整數M (M稱為模)去除而余數相等,則稱A、B對M同余,記作:
A=B (MOD M)
具有同余關系的兩個數為互補關系,其中一個稱為另一個的補碼。當M=12時,-5和+7,-4和+8,-3和+9就是同余的,它們互為補碼。
從同余的概念和上述時鍾的例子,不難得出結論:對於某一確定的模,用某數減去小於模的另一個數,總可以用加上“模減去該數絕對值的差”來代替。因此,在有模運算中,減法就可以化作加法來做。
可以看出,補碼的加法運算所依據的基本關系為:
[x]補+ [y]補= [x+y]補
補碼減法所依據的基本關系式:
[x-y]補 =[x+(-y)]補= [x]補+ [-y]補
至於加法運算為什么比減法運算易於實現以及CPU如何實現各種算術運算等問題,則需要通過對數字電路的學習來理解CPU的運算器的硬件實現問題的相關內容了。
五.
1.一個二進制數的補碼的補碼就是原碼!!!
比如:真值-3,原碼1000 0011,補碼1111 1101,
原碼1111 1101,補碼1000 0011。
也可以從補碼的數學含義理解。
2.幾個特殊的補碼記憶:(一般是8位,不是8位和8的倍數位的,在實際應用中沒有意義,所以一般都是變換成成8位的二進制數。因為實際應用中,一般都是補碼表示,所以着重記憶補碼)
0的補碼是0000 0000
-1的補碼是1111 1111 -1的原碼是1000 0001
-128的補碼是1000 0000
+1的補碼是其原碼。
+1~+127的補碼都是原碼。補碼逐漸加一。
-1~-127的補碼都是其反碼加一。補碼逐漸加一。
雖然補碼的原碼是多少 不夠直觀,但是補碼反映出的負數的大小是直觀的,補碼大小順序和真值保持一致。
負數真值中,-1最大,-128最小,
負數補碼中,-1補碼是1111 1111,...,-127補碼是1000 0001,-128補碼是1000 0000,
在負數的補碼中,直觀上可以看出,-1的補碼是最大的:1111 1111, -128的補碼是最小的:1000 0000。
3.
80H的補碼是多少?
因為有補碼,所以是有符號數。80H即原碼1000 0000,即真值-0,所以80H的補碼是0000 0000。
六.+128
8位二進制數時,表示不下+128,16位二進制數時可以表示。因為+128=0001 0000 0000
8位二進制數的原碼范圍是-127~-0,+0,~127,反碼是-127~-0,+0~+127,補碼范圍是-128~0~+127。范圍都是256個整數。
不包括+128。-128也只在補碼表示中有。-128的原碼和反碼在8位二進制數時也都沒有,在16位及以上可以表示。
七.探究求補碼的最好的方法
-0的原碼是 1000 0000,反碼 1111 1111, 補碼 0000 0000,可以反碼加一,可以對-1求補操作。
-3的原碼是 1000 0011,反碼 1111 1100 ,補碼 1111 1101,可以反碼加一,可以對-3求補操作。
-128原碼是 沒有 反碼 沒有 補碼 1000 0000 可以對-128求補操作。
由上面三個例子可以看出,求補碼的最快捷的方法,第一位不變什么的 只適用於不是-1 -128的大部分數!
最統一的方法,應該是:
有反碼的,反碼加一(其中,符號位有進位的 舍棄符號位 只保留數值位。比如-0的補碼。更重要的是-0的補碼 是規定),或者求補操作。
沒有反碼的,求補操作。比如-128。
所以說,求補操作,才是對-128~+127唯一全部使用的求補碼的方法。
這樣也就解釋了,為什么所有補碼都可以用補碼減法運算了,因為求補操作對所有真值都適用。
求補操作:就是求(負數的)補碼
求補操作:不管符號位(不是符號位保持不變!也不是第一位保持不變!就是只用負數的絕對值,根本沒用到符號位),取負數(真值)的絕對值(即將負數的符號位變為0),對絕對值按位取反(可以認為絕對值是無符號數),然后加一。就得到了負數的補碼。
求補操作對於求-0,-128也都適用。
例子:求3CH-90H。分為有符號數和無符號數時。
0011 1100
- 1001 0000
----------------------
3CH 和90H 不是真值!只有十進制是真值,而 十六進制或者八進制 都是為了書寫二進制碼方便。所以才說3CH可能是無符號數 也可能是有符號數!
3CH 和90H 就是兩個二進制碼!這兩個二進制碼可能是無符號數或者有符號數!
二進制碼(二進制數)分為有符號數和無符號數。
有符號數時,X-Y=X+(-Y)補,所以,求-90H的補碼,即求-1001 0000的補碼。即對-1001 0000求補操作!不是對1001 0000求補操作!90H是絕對值,-90H是真值,1001 0000是絕對值的二進制碼。
--------------------------
這里解釋一下題目要求的意思:
(1)機器只認識二進制。十六進制和八進制是為了人書寫簡潔而設立的。
(2)有符號數和無符號數說的都是二進制數(二進制碼)。
3CH的二進制碼是唯一的,但是當它是有符號數時和是無符號數時 的真值顯然是不同的。
