程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言學習之補碼的深刻理解

C語言學習之補碼的深刻理解

編輯:關於C


學到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。


夜已深,先了解到這一步,以後有更深入的理解再來總結更新。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved