學到C語言的本質之補碼時(http://learn.akae.cn/media/ch14s03.html)。發現不是很理解,特別是這段描述。
如果8個bit采用2'sComplement表示法,
負數的取值范圍是從10000000到11111111(-128~-1),
正數是從00000000到01111111(0~127)。
於是搜索了不少資料,總算理清了這一點。
首先,原碼,反碼,補碼是一個真值用二進制表示的的不同方式。將一個真值表示成二進制字串的機器數的過程就稱為編碼。無符號數沒有原碼、反碼和補碼一說。只有帶符號數才存在不同的編碼方式。
至於為什麼計算機最終選擇補碼來表示呢?具體看這裡
http://sharecourse.upln.cn/courses/c_809_04/theory/module_2/pdf/whybm.pdf
從原碼轉成補碼也看上面的文章。
這裡有一點很重要的,就是從補碼怎麼轉為原碼或者真值呢?
其實這個過程跟從原碼轉成補碼是一樣的。這一點很多學習資料都沒提到。我是在
http://wenwen.soso.com/z/q110390792.htm這裡看到的。
具備了以上知識後,現在來解釋一下補碼的范圍是怎麼回事。
1 先從簡單的開始,正數的范圍,明顯補碼的二進制范圍是從00000000到01111111。那麼取幾個特殊的值來看看,
0000,0000
0111,1111
這兩個二進制的數是誰的補碼呢?
也就是(0000,0000)的真值是?
(0111,1111)的真值是?
由於正數的補碼跟真值是一樣的,
所以(0000,0000)的真值是0,(0111,1111)的真值是127。
由此可見,用補碼來表示正數,取值范圍是0-127。
2 負數的范圍,明顯補碼的二進制范圍是從10000000到11111111。再取幾個特殊值來看看,
那麼10000000的真值是?
10000001的真值是?
11111111的真值是?
上面有說過如何從補碼轉為真值。
計算後,發現
10000000的真值是(-1000,0000)=-128
10000001的真值是(-111,1111)=-127
11111111的真值是(-000,0001)=-1。
所以用補碼表示負數,范圍是-128到-1。
這裡,特地,演算一下。(采取先不管符號位的做法)
10000001(這是補碼)
取反,得 (111,1110)
+1,得(111,1111)
加上符號位(-111,1111)即-127
(1000,0000)(這是補碼)
取反,得(111,1111)
+1,得(1000,0000)
加上符號位,得 –1000,0000,即是-128。
那麼我們驗證一下真值-127的補碼形式是不是(1000,0001)。
-127這是真值,即(-111,1111)
轉為原碼(1111,1111)
取反,轉為反碼(1000,0000)(符號位不變)
+1,(1000,0001)(符號位不變)
再驗證一下真值-128的補碼形式是不是(1000,0000)。
-128(-1000,0000)顯然原碼表示不了。
只能這麼理解法,
先不管符號位,得(1000,0000)。
取反,得(0111,1111)
+1,得(1000,0000),7位溢出了,去掉進位得(000,0000)
補上符號位得(1000,0000)。
其實,我們只要記住真值-128的補碼形式是(1000,0000)就好了。
其實,求反加1的方法是有缺陷的,並不是補碼的定義,了解了補碼的定義,才可以真正了解補碼與真值的轉換。
就是利用同余。http://sharecourse.upln.cn/courses/c_809_04/theory/module_2/pdf/whybm.pdf
在數學中,用“同余”概念描述上述關系,即兩整數 A、B 用同一個正整數 M (M 稱為
模)去除而余數相等,則稱 A、B 對 M 同余,記作:
A=B (MOD M)
具有同余關系的兩個數為互補關系,其中一個稱為另一個的補碼。當 M=12 時,-
5 和+7,-4 和+8,-3 和+9 就是同余的,它們互為補碼。
從同余的概念和上述時鐘的例子,不難得出結論:對於某一確定的模,用某數減去
小於模的另一個數,總可以用加上“模減去該數絕對值的差”來代替。因此,在有
模運算中,減法就可以化作加法來做。
可以發現,有個技巧,互為補碼的兩個數加起來剛好等於模。
對於8位得二進制數,模等於2的8次方=256。
真值-127的補碼是誰呢?
-127等價於 加上模減去127的差,即加上 129(1000,0001)。
因此-127與129(1000,0001)互補。
即真值-127的補碼為(1000,0001),這個補碼看起來是正數,其實表示的是負數。
現在再來看看真值-128的補碼形式是不是(1000,0000)。
顯然,-128等價於加上 256-128=128,即(1000,0000)。
觸類旁通,真值-126的補碼是?
-126等價於加上256-126=130,即(1000,0010)。
上面是,由真值求補碼。
那麼怎麼由補碼求真值呢?
比如補碼(1000,0010)的真值是?
顯然(1000,0010)=130,符號位是1,表示的真值是負數,
130-256=-126。
補碼(1000,0000)的真值是?
顯然,(1000,0000)=128,符號位是1,表示的真值是負數,
128-256=-128。
夜已深,先了解到這一步,以後有更深入的理解再來總結更新。