二進制補碼(負數編碼)、反碼、原碼


 

一、補碼  

補碼是對負整數在計算機中存儲的一種形式;

第二種形式的負數在計算機中可以使用 (負號加數字)的形式表示一個負數;例如(-3 以1000 0011 存儲)但是使用這種方法表示的只有(+0,-0),而且不可以做算術運算。

 

二、計算機數和真值

討論二進制編碼之前,首先來了解一下什么是計算機數和真值

(一)計算機數 

一個數在計算機中的二進制表示形式,叫做這個數的機器數

機器數數帶符號的,由於計算機內部的硬件只能表示兩種物理狀態,在計算機使用一個數的最高位存放符號,正數為 0,負數為 1。

例如:十進制中的 +5 和 -5,計算機字長為8位,分別轉換為 00000101 和 10000101;這里面的 00000101 和 10000101 就是機器數

機器數的特點:

一個數值的二進制表現形式,就叫做這個數的機器數。二進制的位數是受機器設備的限制的。機器內部設備一次能表示的二進制位數叫做機器的字長,一台機器的字長數固定的。

字長8位的叫做一個字節(Byte),機器字長一般都是字節的整數倍,如字長 8位、16位、32位、64位。

機器數的分類:

根據小數點位置固定與否,機器數又可以分為定點數和浮點數。通常使用 定點數表示 整數,使用 浮點數表示 實數:

1、整數:整數沒有小數部分,小數點固定在數的最右邊。整數可以分為(1) 無符號整數 和 (2) 有符號整數 兩類。

無符號整數的所有二進制位全部用來表示數值的大小;

有符號整數用最高位表示數的正負號,其他位數表示數值的大小。

2、實數:實數的浮點數表示方法:將一個實數的范圍和精度分別用階碼和位數表示。在計算機中,為了提高數據表示精度,必須表示小數點的位置,因此浮點數必須寫成規范的形式(位數不為 0 的時候,其絕對值大於或等於 0.5 並且小於 1(因為是二進制位,要求尾數第 1 位必須是 1))。

例如:設機器字長位 16位,尾數為 8位,階碼 為 6位,則二進制實數 -1101.010 的機內表示為 0000100111010100。

注釋:

階碼在機器中表示一個浮點數時需要給出指數,這個指數需要用整數形式表示,這個整數叫做階碼。階碼用以指示小數點在數據中的位置。

 

(二)真值

不帶符號的數是數的絕對值,在絕對值前面加上表示正負的符號就成了符號數。

在計算機數中,第一位是符號位,所以計算機數的形式值就不能等於真正的數值。

-5 的計算機數為 10000101 ,最高位的1代表的是負號,真正的數值應該是 -5 而不應該是由形式值轉換而來的 133。

所以為了區別兩個數值,將帶有符號位的計算機數對應的真正數值稱為 機器數的真值

例如:0000 0001的真值為 +000 0001 即為+1,1000 0001的真值為-000 0001,即為-1;

 

三、原碼、反碼、補碼詳解

計算機需要使用一定的編碼方式進行存儲。原碼、反碼、補碼則是計算機存儲一個具體數字的編碼方式

(一)原碼

原碼的表示方法:

原碼的數值部分就是該數的絕對值,然后再加上符號位。即用第一位表示符號,其余位數表示值。

+1 [原碼] = 0000 0001

-1 [原碼] = 1000 0001

如果是 8位二進制得取值范圍為:[1111 1111 , 0111 1111],即為 [-127,127]

原碼的加減法運算:

兩數相加:機器首先判斷兩個數是否符號相同,如果相同則兩數相加。若符號不同,則兩數相減。

兩數相減相減運算之前,先判斷兩數絕對值的大小,用大數減去小數,然后再確定差值的符號。

這樣的計算顯然是很麻煩的,為了減少設備解決機器內符號位參與運算的問題,總是將減法運算變成加法運算,從而也就引進了反碼和補碼兩種兩種機器數。

 

(二)反碼

反碼的表現方式:

正數,其反碼和原碼的形式相同;

負數,反碼與其原碼的數值部分各位變反;即符號位不變,其余各位取反。

+1 = 0000 0001 [原碼] = 0000 0001 [反碼]

-1 = 1000 0001 [原碼] = 1111 1110 [反碼]

如果一個反碼表示的是負數,直觀上是無法看出它的數值,需要先將其轉換成原碼再進行計算。

 

(三)補碼

補碼的表示方法:

正數補碼和原碼形式相同

負數補碼為其反碼的末位加1

+1 = 0000 0001 [原碼] = 0000 0001 [反碼] = 0000 0001 [補碼]

-1 = 1000 0001 [原碼] = 1111 1110 [反碼] = 1111 1111 [補碼]

補碼的數值通常需要將其轉換為原碼才方便計算其原數值。

補碼是根據 同余 的概念引入的。

通過加法來實現減法的例子:假定當前時間為北京時間 6點整,有一只手表是 8點整,比北京時間快了 2個小時。這時候就有兩種校准方法:(1)倒撥 2小時;(2)正撥 10小時。假設倒撥是做減法,正撥是做加法。

對於手表來說 -2 和 +10是等價的(也就是說減2可以用加10來實現),這是因為這是因為8加10等於18,然而手表最大只能指示12,當大於12時12自然丟失,18減去12就只剩6了

注意:

1、正數的原碼、反碼、補碼的形式是相同的

2、負數的原碼、反碼、補碼其形式各不相同;

3、對於負數的反碼和補碼(即符號位為1的數),其符號位后面的幾位數表示的並不是此數的數值。如果想要知道數值的大小,一定要求其反碼或是補碼才行。

 
 

四、原碼、反碼、補碼的使用

計算機中有三種編碼方式表示一個數,對於正數三種編碼方式返回的結果都是相同的。

+1 = 0000 0001 [原碼] = 0000 0001 [反碼] = 0000 0001 [補碼]

對於這個負數

-1 = 1000 0001 [原碼] = 1111 1110 [反碼] = 1111 1111 [補碼]

只有原碼才是可以直接被識別並且用於計算方式 ,那么反碼和補碼的作用又是什么?

人腦在進行計算的時候可以知道第一位是符號位,在計算的時候會根據符號位選擇對真值的加減。

對於計算機來說,加減乘除是最基礎的運算,要盡量設計的簡單,計算機辨別出 符號位 會使得計算機的基礎電路設計變得更加復雜,所以人們想出了將符號位也參與運算的方法。

減去一個正數等於加上一個負數,即 2-1 = 2+(-1),所以機器只有加法而沒有減法。符號位參與運算,只保留加法運算。

(一)原碼運算:

十進制的運算:1-1=0

1-1=1+(-1) = 0000 0001 [原碼] + 1000 0001 [原碼] = 1000 0010 [原碼] = -2

如果用原碼表示,讓符號位也參與計算,對於減法來說,結果顯然是不正確的,所以計算機內部不使用原碼來表示一個數字。

 

(二)反碼運算:

為了解決原碼做減法的問題,就引出了反碼

十進制的運算:1-1=0

1-1=1+(-1) = 0000 0001 [原碼] + 1000 0001 [原碼] = 0000 0001 [反碼] + 1111 1110 [反碼] = 1111 1111 [反碼] = 1000 0010 [原碼] = -0

使用反碼計算減法,結果的真值部分是正確的,但是在 ‘0’這個特殊的數值上。雖然 +0和 -0在意義上是一樣的,但是0加上符號是沒有任何意義的,0000 0001[原碼] 和1000 0001[原碼] 這兩個編碼都表示0。

 

(三)補碼運算:

補碼的出現,解決了 0 的符號以及兩個編碼的問題。

十進制的運算:1-1 =0

1-1=1+(-1) = 0000 0001 [原碼] + 1000 0001 [原碼] = 0000 0001 [補碼] +  1111 1111[補碼] = 0000 0000[補碼] = 0000 0000[原碼] = 0

這樣 0 用 [0000 0000] 表示 ,而以前出現問題的 -0 就不存在了,而且可以用 [1000 0000] 表示 -128

(-1) + (-127) = 1000 0001[原碼] + 1111 1111[原碼] = 1111 1111[補碼] + 1000 0001[補碼] = 1000 000[補碼] = -128

-1-127 的結果應該是 -128,在用補碼運算的結果中,1000 0000[補碼] 就是-128,但是注意因為實際上使用 -0 的補碼來表示 -128,所以 -128並沒有原碼和反碼表示。(-128的補碼表1000 0000[補碼] 算出來的 0000 0000[原碼] 這樣是不正確的)

使用補碼,不僅是修復了 0的符號以及存在兩個編碼問題,而且還能多表示一個最低數。

注意:

1、所以8 位的二進制,使用原碼或是反碼表示的范圍為 [-127,+127],使用補碼表示的范圍為 [-128,127];

2、常用的32 位二進制,使用補碼表示的范圍為  [-231, 231-1] ,這是因為第一位表示的是符號位,使用補碼表示時又可以多保存一個最小值。

 

五、原碼、反碼、補碼算術運算

(一)反碼的算術運算

反碼的運算注意問題:

1、反碼運算時,符號位與數值一起參與運算;

2、反碼的符號位相加后,如果有進位產生,就要·把進位送回到最低位相加(循環進位);

3、用反碼運算,其運算結果也為反碼。在轉換為真值時,若符號位為0,數位不變;若符號位為1,應將結果求反才是其真值。

[例1] 已知X = + 1101 , Y = + 0110 , 用反碼計算Z = X-Y。

解: [X]反 = 01101,[-Y]反 = 11001,則[Z]反 =[X]反+[-Y]反 = 01101+11001+1(循環進位)= 00111 , 其真值為Z = +0111。

[例2] 已知X = + 0110 , Y = + 1101 , 用反碼計算Z = X-Y。

解: [X]反 = 00110,[-Y]反 = 10010,則[Z]反 =[X]反+[-Y]反 = 00110 + 10010= 11000 , 其真值為Z = - 0111。

采取反碼運算較好的解決了原碼運算所遇到的困難或問題,但由於循環進位需要二次算術相加,延長了計算時間,這同樣給電路帶來麻煩。

而采用下述的補碼運算則可避免循環進位的兩次計算,同時,采用補碼運算對溢出的判斷也較采用反碼簡單的多,所以機器中的算術運算普遍采用補碼運算

 

(二)補碼的算術運算

補碼要注意的問題:

1、補碼運算時,其符號位與數值部分一起參加運算

2、補碼的符號相加后,如果有進位的出現,需要將這個進位舍去(自然丟失)

3、用補碼運算,其運算結果也是補碼。在轉換為真值時,若符號位為 0,數位不變;若符號位為1,應將結果求補才是其真值。

[例3] 已知X = + 1101 , Y = + 0110 , 用補碼計算Z = X-Y。

解: [X]補 = 01101,[-Y]補 = 11010,則[Z]補 =[X]補+[-Y]補 = 01101+11010= 100111 , 其真值為Z = + 0111。

[例4] 已知X = + 0110 , Y = + 1101 , 用補碼計算Z = X-Y。

解: [X]補 = 00110,[-Y]補 = 10011,則[Z]補 =[X]補+[-Y]補 = 00110 + 10011= 11001 , 其真值為Z = - 0111。

 

(三)溢出及補碼溢出的判斷

無論采取什么機器,只要運算的結果大於數值設備所能表示數的范圍,就會產生溢出。溢出現象應該當成是一種故障來處理,因為它使結果數產生錯誤。

異號兩數相加時,實際是兩數的絕對值相減,不可能產生溢出,但有可能出現正常進位;

同號兩數相加時,實際上是兩數的絕對值相加,既可能產生溢出,也可能出現正常進位。

[例5] 某數字設備用五位二進制表示數,計算

(1)9+3 (2)-9-3 (3)9+12 (4)-9-12

解:(1)[+9]補+[+3]補= 01001+ 00011 = 01100 = +12 正確;

(2)[-9]補+[-3]補= 10111+ 11101 = 110100 = 10100(符號位進位自然丟失),其真值為-1100 = -12正確;

(3)[+9]補+[12]補= 01001 + 01100 = 10101 其真值為-1011 =-11錯誤,產生了溢出;

(4)[-9]補+[-12]補 = 10111+10100 = 101011 其真值為01011= +11 錯誤,產生了溢出。

(1)、(2)兩題結果均正確,查其最高位和次高位的進位位,不是均無進位產生,就是均產生進位;(3)、(4)兩題結果均錯誤,查其最高位和次高位的進位位,只有一位產生了進位。此即為判斷機器是正常進位還是溢出的基本依據,在微型機中可用異或電路來實現上述的判斷。

 


 

參考博客:
https://baike.baidu.com/item/%E6%9C%BA%E5%99%A8%E6%95%B0/1096838?fr=aladdin
https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

 


免責聲明!

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



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