轉自:
http://kb.cnblogs.com/a/1450313/
第一次修訂 2009-5-6 14:11
---------------------
1.模的概念(我只講個例子,具體的可以查數學中的 "同餘模")
在日常生活中,有許多化減為加的例子。例如,時鐘是逢12進位,12點也可看作0點。
當將時針從10點調整到5點時有以下兩種方法:
1.將時針逆時針方向撥5格,相當於做減法: 10-5=5
2.將時針順時針方向撥7格,相當於做加法:10+(12-5)=12+5=5 (模為 12)
2.模的運用(採用模得到補碼)
1.補碼的得來:是為了讓負數變成能夠加的正數,so,負數的補碼=模-負數的絕對值
比如:-1 補碼:1111 1111(10000 0000 -1得來)
當一個數要減1的時候,可以直接加 1111 1111
2.原碼的得來:(負數的原碼,直接把對應正數的最高位改為1)
原碼能夠直觀的表示一個負數(能直觀的把真值顯示出來,如 -1為1000 0001
其中最高位表示符號位,不進行算術計算)
3.總結:補碼相加,到第9位才捨棄(模10000 0000)
原碼相加,到第8位捨棄(模1000 0000)
反碼相加,到第8位捨棄(模1000 0000)
3.原碼和補碼之間轉換:
1.補碼=原碼減1,再取反(便於理解)
或 補碼= 反碼+1(便於描述和推理)
2.示範:補碼=原碼減1,再取反
如-1的原碼1000 0001-->1000 0000(減1後)-->1111 1111(取反後)補碼
3.示範:補碼= 反碼+1)
如-1的原碼 1000 0001-->1111 1110(反碼)-->1111 1111(加1)補碼
4.重點:(特別是在有進位的時候)
原碼和反碼的最高位是符號位,不參加算術運算,模為1000 0000(比補碼少一個0)
而補碼所有位都可以相加,模為10000 0000(最高位不是符號位,補碼是通過模 減去 負數絕對值得到的)
5.推斷-128的原碼和補碼(用補碼= 反碼+1)
1.關於原碼1000 0000,表示的是-0,還是-128呢?(答案是-128而不是-0)
1.先看看原碼的概念吧:正數的符號位為0,負數的符號位為1,其它位按照一般的方法來表示數的絕對值
2.0是負數嗎?0既不是正數也不是負數,那麼它的符號位到底是0還是1呢?(0的符號位為0,不能為1)
3.看看負數補碼的公式:負數的補碼=10000 0000(模)-數的絕對值
比如:-1 1111 1111 =10000 0000-0000 0001
-2 1111 1110 =10000 0000-0000 0010
現在假設-0為負數,那麼
-0的補碼應該是10000 0000 - 0(這個0,姑且教0的絕對值吧)=0000 0000
反碼:1111 1111(0000 0000 -1=0000 0000 +1111 1111=1111 1111)
原碼:1000 0000
現在來推-128
-128的補碼:10000 0000 - 1000 0000(+128沒有符號位)=1000 0000
反碼:1111 1111(1000 0000 -1=1000 0000+1111 1111=1111 1111)(補碼-1)
原碼:1000 0000(反碼取反)
從上面看來,一個原碼對應了2個補碼
但是仔細分析:原碼的概念,負數的符號位為1,但是0不是負數,所以不能用此公式
0也不是正數,但是可以把0定義為原碼、反碼和補碼都一樣(即0000 0000)
而且據說可以推斷出0的補碼只有一個(有興趣的 可以去推一下,呵呵)
現在原碼1000 0000就唯一表示-128了,而不會表示出-0,因為-0不能用這個公式計算
現在,補碼1000 0000的原碼是1000 0000(已證明),那麼原碼1000 0000的補碼是1000 0000嗎?
原碼 1000 0000 (-128,進位被捨去)
反碼 1111 1111
補碼 1000 0000(1111 1111(反碼) + 1=1000 0000,這裡實際上真正相加的是1111 1111後面的7位,
第1位是符號位始終不會變,所以,當進到第8位的時候,就表示溢出了,會被捨棄)
2.綜上所述:1.-128的補碼和原碼一樣都是1000 0000,
2.0的原碼、反碼和補碼都一樣(即0000 0000)
3.如果把-0當做負數,1000 0000就會有歧義(事實上0的補碼只有一個0000 0000)
第一次的手稿 2009-5-5 22:47
-----------------
1.使用反碼的意義:
1.使符號位能與有效值部分一起參加運算,從而簡化運算規則。從而可以簡化運算器的結構,提高運算速度;
(減法運算可以用加法運算表示出來。)
2.加法運算比減法運算更易於實現。使減法運算轉換為加法運算,進一步簡化電腦中運算器的線路設計。
2.負數的位元串表示一般用補碼:(如何通過原碼推補碼,特別是-128的解釋)
1.先給出3個原則:
1.因為使用補碼可以將符號位和其他位統一處理,同時,減法也可以按加法來處理,即如果是補碼錶示的數,
不管是加減法都直接用加法運算即可實現。
2.兩個用補碼錶示的數相加時,如果最高位(符號位)有進位,則進位被捨棄(模的概念,補碼的模10000 0000)
比如:1111 1111(-1) +1000 0001(-127)=1000 0000(-128,實際上最高位有3個1,進位一次後,還保留一個1)
1111 1110(-2) + 0000 0100(4) = 0000 0010(2)
3.模的規則:(自己的推斷)
1.補碼的模為10000 0000
2.反碼的模為1000 0000(從反碼的定義也能夠知道,即反碼的運算不涉及符號位)
3.模的解釋
在日常生活中,有許多化減為加的例子。例如,時鐘是逢12進位,12點也可看作0點。
當將時針從10點調整到5點時有以下兩種方法:
1.時針逆時針方向撥5格,相當於做減法: 10-5=5
2.時針順時針方向撥7格,相當於做加法:10+(12-5)=12+5=5 (模為 12)
2.原碼、反碼和補碼的定義:(主要討論負數的)
1.正整數的原碼、反碼和補碼都一樣
2.負數:
1.原碼就是原來的表示方法
2.反碼是 原碼除符號位(最高位)外取反
3.補碼=反碼+1
3.舉例:以一個單位元組來說:(即8位)
-1 原碼 1000 0001(通過原碼得到真值)
反碼 1111 1110
補碼 1111 1111(通過補碼得到二進位)
-2 原碼 1000 0010
反碼 1111 1101
補碼 1111 1110
**如此類推:原碼 1000 0000 (-128)(重點)
反碼 1111 1111
補碼 1000 0000(1111 1111 + 1=1000 0000,這裡實際上真正相加的是1111 1111後面的7位,
第1位是符號位始終不會變,所以,當進到第8位的時候,就表示溢出了,所以會被捨棄,
也就是說反碼的模是1000 0000,而補碼的模是:10000 0000比反碼多一位)
如果用補碼反推原碼
補碼1000 0000
反碼1111 1111(1000 0000 -1=1000 0000+1111 1111(相當於2個補碼相加,可用模的規則)=1111 1111)
原碼1000 0000
4.感慨:很多群人解釋不通了,就武斷的說-128的二進位為1000 0000,並斷定它沒有反碼和原碼,還說是"規定"
而我怎麼也沒有找到官方的這麼個規定(個人覺得這是不嚴謹的也是不負責任的,呵呵)
5.具體的計算示範:
1+(-1)=0
0000 0001 + 1111 1111=0000 0000
1+(-2)=-1
0000 0001 + 1111 1110=1111 1111(-1)
2+(-1)=1
0000 0010 + 1111 1111=0000 0001
(-128)+1=-127
1000 0000 +0000 0001=1000 0001(補)
1000 0001(補碼)
1000 0000(反碼=補碼-1)
1111 1111(原碼 =-127)
3.有一個不正確的解釋,貌似還寫成書了(個人認為)
採用補碼錶示還有另外一個原因,那就是為了防止0的機器數有兩個編碼。原碼和反碼錶示的0
有兩種形式+0和-0,而我們知道,+0和-0是相同的。這樣,8位的原碼和反碼錶示的整數的範圍就是-127~+127
(11111111-01111111),而採用補碼錶示的時候,00000000是+0,即0;10000000不再是-0,而是-128,這樣,
補碼錶示的數的範圍就是-128~+127了,不但增加了一個數得表示範圍,而且還保證了0編碼的唯一性。
我的觀點:包括寫上面的話的人自己也說過,10000000(補碼)沒有反碼和原碼,既然這樣,如何得出結論
1000 0000曾經表示的是-0,其實通過上面的分析,1000 0000是有反碼(1111 1111)和原碼的(1000 0000)
4.一些好的概念:
由於電腦中符號和數字一樣,都必須用位元串來表示,因此,加號或減號也必須用0、1來表示。
用最高位0表示正、1表示負, 這種加號或減號數字化的機內表示形式就稱為“機器數”,
而相應的機器外部用加號或減號表示的數稱為“真值”,將一個真值表示成二進位字串的機器數的過程就稱為編碼
5.參考資料:http://www.cnblogs.com/ASPNET2008/archive/2009/04/29/1446471.html