(轉)原碼、反碼和補碼


(轉)原碼、反碼和補碼
2010-12-08 11:12

關於補碼,看過一些書籍和網文,基本都是在“求反加一”的方法、步驟上反復強調,而對於補碼的本質和定義,討論的不足。這就對初學者的造成了誤導,使得很多人都糾結在-128的補碼求取過程中。
關於反碼和原碼,大家都是在鄭重其事的講解,其實,學過的人都知道,它們的重要性是 0 !
做而論道把自己對於補碼的認識寫在下面,但願對讀者有些幫助。

加法器
計算機里面,只有加法器,沒有減法器,所有的減法運算,都必須用加法進行。
即:減去某個數字(或者說加上某個負數)的運算,都應該研究如何用加法來完成。

模、補數
在日常生活當中,可以看到很多這樣的事情:
把某物體左轉 90 度,和右轉 270 度,在不考慮圈數的條件下,最終的效果是相同的;
把分針倒撥 20 分鍾,和正撥 40 分鍾,在不考慮時針的條件下,效果也是相同的;
把數字 87,減去 25,和加上 75,在不考慮百位數的條件下,效果也是相同的;
……。
上述幾組數字,有這樣的關系:
  90 + 270 = 360
  20 + 40 = 60
  25 + 75 = 100
式中的 360、60 和 100,就是“模”。
式中的 90 和 270、20 和 40,以及 25 和 75,就是一對對“互補”的數字。

知道了“模”,求某個數字的“補數”,就是輕而易舉的了:
如果模為 365,數字 120 的補數為:365 - 120 = 245。

用補數代替原數,可把減法轉變為加法。出現的進位就是模,此時的進位,就應該忽略不計。

二進制數的模
前面說過的十進制數 25 和 75,它們是 2 位數的運算,模是 100,即 1 的后面加上 2 個 0。
如果有 3 位數參加運算,模就是 1000,即 1 的后面加上 3 個 0。
這里的 1000,是十進制數的一千,可以寫成 10^3,即 10 的 3 次方。
推論:有多少位數參加運算,模就是在 1 的后面加上多少個 0。

對於二進制數字,模也是這樣推算。
如果是 3 位二進制數參加運算,模就是 1000,即 1 的后面加上 3 個 0;
那么當 8 位二進制數參加運算,模就是 1 0000 0000,即 1 的后面加上 8 個 0。
16 位二進制數參加運算,模可就大了,是 1 的后面加上 16 個 0。
注意:這里提到的 1、0,都是二進制數。
8 位二進制數的模可以按照十進制寫成 2^8,即 256。
16 位數二進制數的模,就是 2^16,按照十進制,它就是 65536。

二進制數的補碼
求二進制數的補數,目的是往計算機里面存放。
在計算機里面,存放的數字什么的,都稱為機器碼;那么二進制形式的補數,也就改稱為補碼了。
一般情況下,都是以 8 位二進制數來討論補碼,少數也有用 16 位數的。

計算時加上正數,是不需要進行求取補數的;只有進行減法(或者加上負數),才需要對減數求補數。
補碼就是按照這個要求來定義的:正數不變,負數即用模減去絕對值。

已知一個數 X,其 8 位字長的補碼定義為:

      / X 0 <= X <= +127 ;正數和0的補碼,就是該數字本身
 [X]補 = |
      \ 2^8 -|X| -128 <= X < 0 ;負數的補碼,就是用 1 0000 0000,減去該數字的絕對值

例如 X = -126,其補碼為 1000 0010,計算方法如下:

    1 0000 0000
   - 0111 1110
 -----------
     1000 0010

可以看出,按照補碼的定義來求補碼,概念十分清晰,方法、步驟也是十分簡單的。

應用補碼進行計算
用補碼計算:83-25=58。

    83  ---都變成補碼,再用加法運算-->  0101 0011
  - 25  -> 1 0000 0000 - 0001 1001-> + 1110 0111
 -----          --------
    58  <--忽略進位1,結果就是正確的--[1] 0011 1010

計算結果如果超出了-128~+127的范圍,結果將是錯誤的,這是沒有辦法糾正的。

應用補碼進行計算,完全符合前面介紹的“用補數可把減法轉換成加法”的做法,只要忽略進位(這個進位1,就是求補的時候,加進去的1 0000 0000中的1),結果就是正確的。

這些關於補數、補碼的定義、方法、步驟,讀者如果看懂了前面的文字,相信大家自己都可以總結出來。
那么為什么總有些網友要提出關於求取補碼的問題呢?
在做而論道看來,就是因為很多教材和網文都在這個問題上“畫蛇添足”。

關於補碼的蛇足
補碼出現后,后人又補充了不少“蛇足”:符號位、求反加一、原碼、反碼......。
下面的表格給出了一些 8 位數的補碼。

--符號位
從這個表格中,可以看出特點:正數的最高位都是0,負數的最高位都是1
這樣一來,有人就把最高位理解成了符號位。說什么是規定的用0代表正號,......。並且鄭重其事的補充說明:“符號位也參加運算”。真能忽悠!賣拐、賣車的都甘拜下風。
其實,前面說過的 補數 和 補碼的定義式 里面,根本就沒有什么符號位。這最高位的1、0是自然出現的,並不是由人來規定的。
--求反加一
負數補碼的后面七位,也可以看出一個不完全的規律:它們和絕對值之間存在着“求反加一”的關系。
於是,又有人推出了這個不同於定義式的算法
--原碼和反碼
由於使用“求反加一”來求取補碼,順便又引出了 原碼 和 反碼 兩個垃圾概念。

其實,“求反加一”的計算方法只是適用於計算二進制形式的補數,它並不是通用的。
並且把“求反加一”用於求-128的補碼,有個溢出的現象,很多人都在這里被弄瘸了很長時間。
原碼和反碼也只不過是“人工”進行“求反加一”時的中間過程,在計算機里面根本是不存在的,它們也就沒有絲毫用處

做而論道的建議
求取補碼,就按照定義的規定,負數采用“模減去絕對值”的方法來求,這是求補數的通用方法,適合於各種進制、各種大小的數字。
不要用求反加一的方法,也就不用理會原碼和反碼了,也不牽涉符號位的問題。
以后的計算,也就沒有必要特殊說明:“符號位一起參加運算...”,因為根本就沒有什么符號位。

如果把原碼和反碼、符號位等等垃圾概念,從計算機的書中刪減掉,學習補碼將會省力不少。

http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/blog/item/d92cc986c2a1523bc75cc380.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM