1.3 编码

数字系统中,任何数据和信息多少使用若干位 "0" 和 "1" 按照一定的规则组成的二级制码来表示的。nnn 位二进制数码可以组成 2n2^n2n 中不同的代码,代表 2n2^n2n 中不同的信息或数据。用若干位二进制数码按一定规律排列起来表示给定信息的过程称为编码

一、带符号数的编码

1、带符号数

数字系统中(如计算机)必须能够同时处理正数和负数。带符号的二进制数含有符号和数值信息,符号表明这个数是正数还是负数,而数值就是这个数的值。代码的位数称为字长 ,它的数值称为真值 。在二进制中,带符号整数有三种表示方法:原码、反码和补码 。其中补码是最重要的,原码很少用。

带符号的二进制数最左边的一位是符号位 ,用来指明这个数是正数还是负数,符号位为 000 表示正数,为 111 表示负数

2、原码

用原码表示带符号的二进制数时,最左边一位是符号位,其余的都是数值位。数值位对正数和负数来讲都是以真实的二进制数形式出现。

例如,真值分别为 +62+62+62 和 −62-62−62,用 888 位字长的原码表示如下:N=+62D=+0111110B[N]原=00111110N=−62D=−0111110B[N]原=10111110\begin{array}{ll}N=+62_{\textrm D}=+0111110_{\textrm B}&&&&[N]原=00111110\\N=-62{\textrm D}=-0111110_{\textrm B}&&&&[N]_原=10111110\end{array}N=+62D=+0111110BN=−62D=−0111110B[N]原=00111110[N]原=10111110注意观察上面的表示,+62+62+62 和 −62-62−62 之间只有符号位不同,原码形式中,负数和其相应的正数具有相同的数值位,但是符号位为 111 而不是 000. 由于原码进行减法运算时,电路结构复杂,不容易实现,因此又引入了反码和补码。

3、反码

反码的表示方法:正数的反码与其原码相同;负数的反码是符号位为 111,数值位各位取反,也是其对应正数的反码(这里指的的对应正数各位取反,实际正数的反码与其原码一样,注意区分)。

例如,真值为 +45+45+45 和 −45-45−45,用 888 位字长的反码来表示如下:[+45]原=00101101[+45]反=00101101[−45]原=10101101[−45]反=11010010\begin{array}{lllll}[+45]_原=00101101&&&&[+45]_反=00101101\\ [-45]_原=10101101&&&&[-45]_反=11010010\end{array}[+45]原=00101101[−45]原=10101101[+45]反=00101101[−45]反=11010010

4、补码

数值位为 nnn 位(不包括符号位)的二进制整数 NNN 的补码表示为:[N]补={N(N 为正数)2n−N(N为负数)[N]_补=\left\{\begin{array}{lr}N&&&(N\,为正数)\\2^n-N&&&(N为负数)\end{array}\right.[N]补={N2n−N(N为正数)(N为负数)补码的意义和补角的意义类似,这里就是它们两个互为最大值的补数。由于 2n−12^n-12n−1 是 nnn 为全为 111 的二进制数,所以负数的补码又可以写成 (2n−1)−N+1(2^n-1)-N+1(2n−1)−N+1,而 (2n−1)−N(2^n-1)-N(2n−1)−N 就是对 NNN 的每一位取反(注意这里的 NNN 不包括符号位)。因此,正数和负数求补码的方式为:

(1)正数和 000 的补码与原码相同;

(2)负数的补码是保持其原码的符号位不变,对数值位逐位求反,然后在最低位加 111;即负数的补码就是其反码加 111,保持符号位不变。负数的补码是相应正数的补码(反码+1).

nnn 位字长的二进制原码、反码、补码所表示的十进制的数值范围是:

  • 原码:−(2n−1−1)∼+(2n−1−1)-(2^{n-1}-1)\sim+(2^{n-1}-1)−(2n−1−1)∼+(2n−1−1)
  • 反码:−(2n−1−1)∼+(2n−1−1)-(2^{n-1}-1)\sim+(2^{n-1}-1)−(2n−1−1)∼+(2n−1−1)
  • 补码:−2n−1∼(2n−1−1)  (不含−0)-2^{n-1}\sim(2^{n-1}-1)\,\,(\pmb{不含-0})−2n−1∼(2n−1−1)(不含−0)

例如:444 位字长的原码、反码其数值表示范围均为 −7∼+7-7\sim+7−7∼+7,而补码的范围是 −8∼+7-8\sim+7−8∼+7;+0+0+0 的原码、反码、补码均为 000000000000,−0-0−0 只有原码 (1000)(1000)(1000) 和反码 (1111)(1111)(1111),没有补码;−8-8−8 只有补码 (1000)(1000)(1000),没有原码和反码。

如果已知一个数的补码,可以使用 {[X]补}补=[X]原\{[X]_补\}_补=[X]_原{[X]补}补=[X]原 求其原码和真值,即补码的补码就是原码

例1 】已知十进制数 +6+6+6 和 −5-5−5,试分别用 444 位字长和 888 位字长的二进制补码来表示。
解: (1)n=4n=4n=4 时:[+6]原=0110[+6]补=0110[−5]原=1101[−5]补=1011\begin{array}{l}[+6]_原=0110&&&&[+6]_补=0110\\ [-5]_原=1101&&&&[-5]_补=1011\end{array}[+6]原=0110[−5]原=1101[+6]补=0110[−5]补=1011(2)n=8n=8n=8 时:[+6]原=00000110[+6]补=00000110[−5]原=10000101[−5]补=11111011\begin{array}{l}[+6]_原=00000110&&&&[+6]_补=00000110\\ [-5]_原=10000101&&&&[-5]_补=11111011\end{array}[+6]原=00000110[−5]原=10000101[+6]补=00000110[−5]补=11111011【例2 】已知 444 为字长的二进制补码分别为 0011、1011、10000011、1011、10000011、1011、1000,试求出相应的十进制数。
解: (1)因为 [X]补=0011[X]_补=0011[X]补=0011,符号位为 000,所以 [X]原=0011[X]_原=0011[X]原=0011,X=+3X=+3X=+3.

(2)因为 [X]补=1011[X]_补=1011[X]补=1011,符号位为 111,所以 [X]原=[1011]补=1101[X]_原=[1011]_补=1101[X]原=[1011]补=1101,X=−5X=-5X=−5.

(3)因为 [X]补=1000[X]_补=1000[X]补=1000,符号位为 111,它是 n=4n=4n=4 时 −8-8−8 的补码,而 −8-8−8 没有原码和反码,所以 X=−8X=-8X=−8.

5、带符号数的运算

在数字系统中,可以很容易的求这个数的反码和补码,使用补码对于带符号二进制数的加、减法运算很方便。

(1)加法

两个带符号二进制数相加时,有下面四种情况:

  1. 两个数都是正数;
  2. 正数的数值大于负数的数值;
  3. 负数的数值大于正数的数值;
  4. 两个数都是负数。

下面使用 888 位的带符号二进制数来对每一种情况进行举例,并给出十进制数的对照,注意,带符号二进制数的补码相加时,符号位会参与运算

  • 两个数都是正数: 000001117+00000100+4---------------------0000101111\begin{array}{rr}00000111&&\kern 7pt7\\+00000100&&+4\\---------------&&------\\00001011&&\kern 7pt11\end{array}00000111+00000100---------------000010117+4------11和为正数,因此得到这个也是带符号二进制数的原码。两个正数相加得到一个正数。
  • 正数的数值大于负数的数值: 0000111115+11111010+−6------------------------丢弃进位→1 000010019\begin{array}{rrr}00001111&&15\\+11111010&&+-6\\---------------&&---------\\{\color{blue}丢弃进位\rightarrow1}\,00001001&&9\end{array}00001111+11111010---------------丢弃进位→10000100115+−6---------9丢弃进位后和为正数,这个也是带符号数的二进制原码。正数加上一个数值比它小的负数得到一个正数。
  • 负数的数值大于正数的数值: 0001000016+11101000+−24------------------------11111000−8\begin{array}{rrr}00010000&&16\\+11101000&&+-24\\---------------&&---------\\11111000&&-8\end{array}00010000+11101000---------------1111100016+−24---------−8和为负数,是补码形式。
  • 两个数都是负数: 11111011−5+11110111+−9------------------------丢弃进位→1 11110010−14\begin{array}{rrr}11111011&&-5\\+11110111&&+-9\\---------------&&---------\\{\color{blue}丢弃进位\rightarrow1}\,11110010&&-14\end{array}11111011+11110111---------------丢弃进位→111110010−5+−9---------−14舍去进位,和为负,所以是补码形式。

一个正数加上一个数值比它大的负数,或者两个负数相加,都会得到一个补码形式的负数。在计算机中,负数都是以补码形式存储的,加法的过程很简单,只要将两个数加起来,并舍去进位即可

溢出条件: 当两个数相加时,如果表示所需的位数超过了这两个数的位数,就会发生溢出,溢出的结果是出现了错误的符号位。只有当两个数都是正数或者两个数都是负数的情况下才会发生溢出,如果相加的结果的符号位与两个相加数的符号位不同,则表明发生了溢出 。如 125+58125+58125+58 的情形:01111101125+00111010+58------------------------符号位错误→10110111←大小错误183\begin{array}{rrr}01111101&&125\\+00111010&&+\kern 7pt58\\---------------&&---------\\{\color{blue}符号位错误\rightarrow\boxed{1}}{\color{red}\boxed{0110111}}&\color{red}\leftarrow大小错误&183\\\end{array}01111101+00111010---------------符号位错误→10110111←大小错误125+58---------183上述例子中,和 183183183 需要 888 个数值位,而数中只有 777 个数值位,另一个是符号位,进位进入符号位后就会产生溢出,导致结果错误。

(2)减法

减法实际上是加法的一个特例。例如,+9+9+9(被减数) 减去 +6+6+6(减数),就相当于 +9+9+9 加上 −6-6−6. 减法运算实际上是改变减数的符号然后加到被减数上,减法的结果为差。

例3 】试用 444 位字长的二进制补码完成下列运算:
①7−5②3−4① 7-5\kern 20pt ② 3-4①7−5②3−4
解: [7]补=0111,[−5]补=1011,[3]补=0011,[−4]补=1100[7]_补=0111,[-5]_补=1011,[3]_补=0011,[-4]_补=1100[7]补=0111,[−5]补=1011,[3]补=0011,[−4]补=1100

① [7]补+[−5]补[7]_补+[-5]_补[7]补+[−5]补 为0111+1011---------舍去进位→1 0010\begin{array}{r}0111\\+1011\\---------\\{\color{blue}舍去进位\rightarrow1}\,0010\end{array}0111+1011---------舍去进位→10010即 [7−5]补=[7]补+[−5]补=0010[7-5]_补=[7]_补+[-5]_补=0010[7−5]补=[7]补+[−5]补=0010,符号位为 000,所以 [7−5]原=0010[7-5]_原=0010[7−5]原=0010,即 7−5=+27-5=+27−5=+2.

② [3]补+[−4]补[3]_补+[-4]_补[3]补+[−4]补 为0011+1100---------1111\begin{array}{rr}0011\\+1100\\---------\\1111\end{array}0011+1100---------1111即 [3−4]补=[3]补+[−4]补=1111[3-4]_补=[3]_补+[-4]_补=1111[3−4]补=[3]补+[−4]补=1111,符号位为 111,所以 [3−4]原=1001[3-4]_原=1001[3−4]原=1001,即 3−4=−13-4=-13−4=−1.

(3)乘法

乘法中,我们用将其中的数称为被乘数、乘数和积。下面以十进制的乘法举例说明:8←被乘数×3←乘数------24←积\begin{array}{rrl}8&\leftarrow&被乘数\\\times3&\leftarrow&乘数\\------\\24&\leftarrow&积\end{array}8×3------24←←←被乘数乘数积在大多数计算机中,乘法运算都是通过加法来完成的,其中直接相加部分积是两种基本方法。

直接相加法 :该方法中,被乘数自身相加的次数等于乘数。如十进制的例子中计算 8×38\times38×3,就是 333 个被乘数相加:8+8+8=248+8+8=248+8+8=24. 这种方法的缺点是,如果乘数很大,那么运算变得就会很冗长。例如,要计算 350×75350\times75350×75 时,需要把 350350350 自身相加 757575 次。这就是术语次数 (times)(\textrm{times})(times) 表示乘法的原因。乘法相当于一个数加上它本身,相加的次数就是乘数。
两个二进制数相乘时,这两个数必须都是原码。下面举例说明:

例4 】使用直接相加法,计算两个带符号的二进制数 010011010100110101001101 (被乘数)和乘数 000001000000010000000100 (乘数)相乘。

解: 由于这两个数都是正数,因此也都是原码,积也为正数。乘数的十进制的数值是 444,所以被乘数自身要相加 444 次:01001101第 1 次+01001101第 2 次---------------10011010部分和+01001101第 3 次---------------11100111部分和+01001101第 4 次---------------100111100乘积\begin{array}{rl}01001101&第\,1\,次\\+01001101&第\,2\,次\\---------------\\10011010&部分和\\+01001101&第\,3\,次\\---------------\\11100111&部分和\\+01001101&第\,4\,次\\---------------\\\color{blue}100111100&乘积\end{array}01001101+01001101---------------10011010+01001101---------------11100111+01001101---------------100111100第1次第2次部分和第3次部分和第4次乘积注意,这里如果只有 888 位字长进行存储,则发生了溢出错误。

部分积法: 部分积分是更常用的一种方法,因为它反映出了手工乘法的运算方式。从乘数的最低位开始,被乘数乘以乘数的每一位。被乘数乘以一个乘数位的结果称为部分积,每一个相继的部分积都向左平移一位,当所有的部分积产生时,再把它们加起来就得到了最终的乘积。先看一下十进制部分积的情况:239被乘数×123乘数------717第 1 个部分积 (3×239)478第 2 个部分积 (2×239)+239第 3 个部分积 (1×239)---------29397最终乘积\begin{array}{rll}239&&被乘数\\\times123&&乘数\\------\\717&&第\,1\,个部分积\,(3\times239)\\478\kern 4pt&&第\,2\,个部分积\,(2\times239)\\+239\kern 9pt&&第\,3\,个部分积\,(1\times239)\\---------\\29397&&最终乘积\end{array}239×123------717478+239---------29397被乘数乘数第1个部分积(3×239)第2个部分积(2×239)第3个部分积(1×239)最终乘积乘法运算积的符号取决于被乘数和乘数的符号,依据下面的两条原则:

  • 如果符号相同,积为正值。
  • 如果符号相异,积为负值。

二进制数的乘法的部分积分法的步骤如下:

  1. 确定被乘数和乘数的符号是相同还是不同,以确定积的符号;
  2. 将负数变为原码形式。因为大多数计算机都是以补码的形式来保存负数,补码运算需要将负数转成原码;
  3. 从最低的乘数位开始,得到部分积。当乘数的位为 111 时,部分积与被乘数相同;当乘数为 000 时,部分积就是 000. 将每一个相继的部分积左移一位;
  4. 将所有的部分积相加,得到最终的积。
  5. 如果步骤 111 所确定的符号位是负的,就对积取补码;如果符号位是正的,积就保持原码。

例5 】求两个带符号二进制数 010100110101001101010011(被乘数)和 110001011100010111000101(乘数)的乘积。
解: (1)被乘数的符号位为 000,乘数的符号位为 111,所以积的符号位为 111(负数)。

(2)取乘数的补码,将其变成原码(变为正数) 11000101→0011101111000101\rightarrow0011101111000101→00111011(3)和(4)的计算过程如下,注意这些步骤中只使用了数值位1010011被乘数×0111011乘数------------1010011第 1 个部分积+1010011第 2 个部分积---------------11111001和+0000000第 3 个部分积---------------011111001和+1010011第 4 个部分积------------------1110010001和+1010011第 5 个部分积------------------100011000001和+1010011第 6 个部分积---------------------1001100100001和+0000000第 7,个部分积---------------------1001100100001最终积\begin{array}{rrlr}1010011&&被乘数\\\times0111011&&乘数\\------------\\1010011&&第\,1\,个部分积\\+1010011\kern 5pt&&第\,2\,个部分积\\---------------\\11111001&&和\\+0000000\kern 10pt&&第\,3\,个部分积\\---------------\\011111001&&和\\+1010011\kern 15pt&&第\,4\,个部分积\\------------------\\1110010001&&和\\+1010011\kern 20pt&&第\,5\,个部分积\\------------------\\100011000001&&和\\+1010011\kern 25pt&&第\,6\,个部分积\\---------------------\\1001100100001&&和\\+0000000\kern 30pt&&第\,7,个部分积\\---------------------\\1001100100001&&最终积\end{array}1010011×0111011------------1010011+1010011---------------11111001+0000000---------------011111001+1010011------------------1110010001+1010011------------------100011000001+1010011---------------------1001100100001+0000000---------------------1001100100001被乘数乘数第1个部分积第2个部分积和第3个部分积和第4个部分积和第5个部分积和第6个部分积和第7,个部分积最终积(5)由于积的符号是 111,所以求积的补码1001100100001→01100110111111001100100001\rightarrow01100110111111001100100001→0110011011111最后再附上符号位,所得积的补码为1 0110011011111\pmb{1\,0110011011111}10110011011111其十进制的运算为 83×(−59)=−489783\times(-59)=-489783×(−59)=−4897.

(4)除法

我们称除法运算中的数分别为被除数、除数和商。如下所示:被除数/除数=商被除数/除数=商被除数/除数=商计算机中除法运算是通过减法来完成的,由于减法是由加法来完成的,因此,除法也可以通过加法来完成。

除非的结果是商,商是被除数中可以减去多少次除数的次数,下面以 212121 除以 777 为例说明:21被除数−7第 1 次减去除数------14第 1 个部分余数−7第 2 次减去除数------7第 2 个部分余数−7第 3 次减去除数------0余数为 0\begin{array}{rrl}21&&被除数\\-7&&第\,1\,次减去除数\\------\\14&&第\,1\,个部分余数\\-7&&第\,2\,次减去除数\\------\\7&&第\,2\,个部分余数\\-7&&第\,3\,次减去除数\\------\\0&&余数为\,0\end{array}21−7------14−7------7−7------0被除数第1次减去除数第1个部分余数第2次减去除数第2个部分余数第3次减去除数余数为0在上述例子中,在余数为 000 前除数从被除数中减去了 333 次,所以商为 333.

商的符号取决于被除数和除数的符号,依据下面的两条原则:

  • 如果符号相同,商为正;
  • 如果符号不同,商为负。

两个二进制数相除时,这两个数都必须是原码形式,除法的步骤如下:

  1. 确定被除数和除数的符号是相同还是不同,用以确定商的符号。商的初始值为 000.
  2. 使用补码加法把除数从被除数中减去,得到第一个部分余数,同时将商加 111,如果这个部分余数是正的,则转到 333;如果部分余数是 000 或者负的,除法就完成了。
  3. 从部分余数中减去除数,商加上 111. 如果结果是正的,重复以上步骤得到下一个部分余数。如果结果是 000 或者负数,完成除法。

继续从被除数和部分余数中减去除数,直至部分余数出现 000 或者负数的结果,计算除数被减的次数,就得到了商。下例中以 888 位带符号的二进制数举例说明:

例6 】计算 011001000110010001100100 除以 000110010001100100011001.

解:(1)这两个数的符号都是正的,所以商也为正数,商的初始值为零:000000000000000000000000.

(2)使用补码加法从被除数中减去除数(记住要舍去最后的进位)01100100被除数+11100111除数的补码---------------舍去进位→1 01001011正的第 1 个部分余数\begin{array}{rrl}01100100&&被除数\\+11100111&&除数的补码\\---------------\\{\color{blue}舍去进位\rightarrow1}\,01001011&&正的第 \,1\,个部分余数\end{array}01100100+11100111---------------舍去进位→101001011被除数除数的补码正的第1个部分余数商的值加 111:00000000+00000001=0000000100000000+00000001=0000000100000000+00000001=00000001.

(3)使用补码加法从第一个部分余数中减去除数01001011第 1 个部分余数+11100111除数的补码---------------舍去进位→1 00110010正的第 2 个部分余数\begin{array}{rrl}01001011&&第\,1\,个部分余数\\+11100111&&除数的补码\\---------------\\{\color{blue}舍去进位\rightarrow1}\,00110010&&正的第\,2\,个部分余数\end{array}01001011+11100111---------------舍去进位→100110010第1个部分余数除数的补码正的第2个部分余数商的值加 111:00000001+00000001=0000001000000001+00000001=0000001000000001+00000001=00000010.

(4)使用补码加法从第二个部分余数中减去除数00110010第 2 个部分余数+11100111除数的补码---------------舍去进位→1 00011001正的第 3 个部分余数\begin{array}{rrl}00110010&&第\,2\,个部分余数\\+11100111&&除数的补码\\---------------\\{\color{blue}舍去进位\rightarrow1}\,00011001&&正的第\,3\,个部分余数\end{array}00110010+11100111---------------舍去进位→100011001第2个部分余数除数的补码正的第3个部分余数商的值加 111:00000010+00000001=0000001100000010+00000001=0000001100000010+00000001=00000011.

(5)使用补码加法从第三个部分余数中减去除数00011001第 3 个部分余数+11100111除数的补码---------------舍去进位→1 00000000余数 0\begin{array}{rrl}00011001&&第\,3\,个部分余数\\+11100111&&除数的补码\\---------------\\{\color{blue}舍去进位\rightarrow1}\,00000000&&余数\,0\end{array}00011001+11100111---------------舍去进位→100000000第3个部分余数除数的补码余数0商的值加 111:00000011+00000001=0000010000000011+00000001=\pmb{00000100}00000011+00000001=00000100(最终的商),至此计算完成。

上述例子中的十进制除法为: 100/25=4100/25=4100/25=4.

二、二 - 十进制编码(BCD码)

二 - 十进制编码是用 444 位二进制编码来表示十进制数字的一种方法,简称 BCD\textrm{BCD}BCD 码(Binary Coded Decimal). BCD\textrm{BCD}BCD 码中只有 101010 个编码组 0∼90\sim90∼9,444 位二进制数码可以有 161616 种组合,所以会有 666 种组合不会使用。虽然选择有很多种,但是实用的并不多。BCD\textrm{BCD}BCD 码提供了一个很好的与二进制系统的接口,键盘输入和数字示值读数一般就采用这种方式。

表 1.3.11.3.11.3.1 列出来几种常用的 BCD\textrm{BCD}BCD 码的编码方式:

1、8421 BCD 码

842184218421 码是最常用的 BCD\textrm{BCD}BCD 码,它用 444 位二进制码来表示每个十进制数字 0∼90\sim90∼9,每一位的权值是 8、4、2、18、4、2、18、4、2、1,这也是名字的来源。8421 BCD8421\,\textrm{BCD}8421BCD 码只选用了二进制码中的前 101010 组,即使用 0000∼10010000\sim10010000∼1001 分别表示 0∼90\sim90∼9,剩下的 666 组编码不使用。这种编码的优势是可以很容易的和我们所熟悉的十进制数进行转换。
无效码 444 位的二进制码可以表示 161616 个数(0000∼11110000\sim11110000∼1111),但是 842184218421 码中,只使用了十个组合,666 个没用的码组合分别为 1010、1011、1100、1101、11101010、1011、1100、1101、11101010、1011、1100、1101、1110 和 111111111111,这些码组合在 842184218421 码中是无效的,因此称为无效码。
BCD\textrm{BCD}BCD 码的加法: BCD\textrm{BCD}BCD 码是数字编码,它可以进行算术运算。加法是最重要的运算,因为其它三种运算(减法、乘法、除法)都可以通过加法来实现。下面是两个 BCD\textrm{BCD}BCD 码相加的步骤,以 842184218421 码为例:

(1)使用二进制的加法法则,将两个 BCD\textrm{BCD}BCD 码相加;

(2)如果 444 位和等于或小于 999,则它就是一个正确的 BCD\textrm{BCD}BCD 码;

(3)如果 444 位和比 999 大,或者存在进位,则这个结果就不正确,要在 444 位和上再加上 666,即 011001100110 来跳过 666 个无效码,从而得到正确的 842184218421 码。如果在加 666 的过程中产生了进位,那么只需要将这个进位加到下一个 444 位组中即可。

例7 】将下面的 BCD\textrm{BCD}BCD 码相加:(a) 0011+0100(b) 00100011+00010101(c) 1001+0100(d) 1001+1001(e) 00010110+00010101(f) 01100111+01010011\begin{array}{lll}(a)\,0011+0100&(b)\,00100011+00010101&(c)\,1001+0100\\(d)\,1001+1001&(e)\,00010110+00010101&(f)\,01100111+01010011\end{array}(a)0011+0100(d)1001+1001(b)00100011+00010101(e)00010110+00010101(c)1001+0100(f)01100111+01010011解: 计算过程如下,同时给出十进制的加法运算作为对比
(a)00113(b)0010 001123+0100+4+0001 0101+15------------------------------------011170011 100038(c)10019+0100+4---------------1101无效 BCD 码 (>9)13+0110加 6---------------0001 0011有效 BCD 码(d)10019+1001+9---------------0001 0010有进位无效18+0110加 6------------0001 1000有效 BCD 码(e)0001 011016+0001 0101+15---------------------0010 1011右边组无效 (>9)31+0110无效码加 6,进位加到下一组---------------0011 0001有效 BCD 码(f)0110 011167+0101 0011+53---------------------1011 1010两组均无效120+0110 0110两组均加 6---------------------0001 0010 0000有效的 BCD 码\begin{array}{l}\begin{array}{lrrrlrrr}(a)&0011&3&&&(b)&0010\,0011&23\\&+0100&+4&&&&+0001\,0101&+15\\&---------&------&&&&---------------&------\\&\pmb{0111}&7&&&&\pmb{0011\,1000}&38\end{array}\\\begin{array}{lrlr}(c)&1001&&9\\&+0100&&+4\\&---------&&------\\&1101&无效\,\textrm{BCD}\,码\,(>9)&13\\&+0110&加\,6\\&---------------\\&\pmb{0001\,0011}&有效\,\textrm{BCD}\,码\end{array}\\\begin{array}{lrlr}(d)&1001&&9\\&+1001&&+9\\&---------&&------\\&0001\,0010&有进位无效&18\\&+0110&加\,6\\&------------\\&\pmb{0001\,1000}&有效\,\textrm{BCD}\,码\end{array}\\[2ex]\begin{array}{lrlr}(e)&0001\,0110&&16\\&+0001\,0101&&+15\\&---------------&&------\\&0010\,1011&右边组无效\,(>9)&31\\&+0110&无效码加\,6,进位加到下一组\\&---------------\\&\pmb{0011\,0001}&有效\,\textrm{BCD}\,码\end{array}\\\begin{array}{lrlr}(f)&0110\,0111&&67\\&+0101\,0011&&+53\\&---------------&&------\\&1011\,1010&两组均无效&120\\&+0110\,0110&两组均加\,6\\&---------------------\\&\pmb{0001\,0010\,0000}&有效的\,\textrm{BCD}\,码\end{array}\end{array}(a)0011+0100---------01113+4------7(b)00100011+00010101---------------0011100023+15------38(c)1001+0100---------1101+0110---------------00010011无效BCD码(>9)加6有效BCD码9+4------13(d)1001+1001---------00010010+0110------------00011000有进位无效加6有效BCD码9+9------18(e)00010110+00010101---------------00101011+0110---------------00110001右边组无效(>9)无效码加6,进位加到下一组有效BCD码16+15------31(f)01100111+01010011---------------10111010+01100110---------------------000100100000两组均无效两组均加6有效的BCD码67+53------120

2、5421 BCD 码和 2421 BCD 码

5421 BCD5421\,\textrm{BCD}5421BCD 码和 2421 BCD2421\,\textrm{BCD}2421BCD 码都是有权码,它们从高位到低位的权值分别为 5、4、2、15、4、2、15、4、2、1 和 2、4、2、12、4、2、12、4、2、1. 这两种 BCD\textrm{BCD}BCD 码的编码方案不唯一。例如:5421 BCD5421\,\textrm{BCD}5421BCD 码中的 555 可以用 100010001000 表示,也可以用 010101010101 表示;2421 BCD2421\,\textrm{BCD}2421BCD 码中的 666 可以用 110011001100 表示,也可以用 011001100110 来表示,表 1.3.11.3.11.3.1 只列出了一种常用的编码方式。

表 1.3.11.3.11.3.1 中所示的 2421 BCD2421\,\textrm{BCD}2421BCD 码中,000 和 999、111 和 888、222 和 777、333 和 666、444 和 555 的代码对应的恰好一个是 000 时,另一个就是 111,我们称 000 和 999、111 和 888、222 和 777、333 和 666 以及 444 和 555 这些互为反码。因此 2421 BCD2421\,\textrm{BCD}2421BCD 码具有对 999 互补的特点,它是一种对 999 的自补代码(即只要对某一组代码的各为取反就可以得到 999 的补码),这在运算电路中使用很方便。

3、余 3 码

余 333 码是在 8421 BCD8421\,\textrm{BCD}8421BCD 的每个 BCD\textrm{BCD}BCD 码都加上 3(0011)3(0011)3(0011) 形成的。余 333 码也具有对 999 互补的特点,它也是一种 999 的子补码,所以也常用于 BCD\textrm{BCD}BCD 码的运算电路中。

用 BCD\textrm{BCD}BCD 码可以分方便的表示多位十进制数,我们只需要对每一位十进制数都用一组 BCD\textrm{BCD}BCD 码代替即可,例如:(579.8)10=(0101 0111 1001.1000)8421 BCD=(1000 1010 1100.1011)余 3 码(579.8){10}=(0101\,0111\,1001.1000){8421\,\textrm{BCD}}=(1000\,1010\,1100.1011)_{余\,3\,码}(579.8)10=(010101111001.1000)8421BCD=(100010101100.1011)余3码

三、可靠性编码

代码在形成、传输过程中可能会发生错误。为了减少这种错误,出现了可靠性编码。下面介绍常用的两种可靠性编码。

1、格雷码(Gray 码)

格雷码是无权码,不是一个算术编码;格雷码位的位置没有指定的权。格雷码的一个重要特征是:任何相邻的两个码组,只有一位数码不同,它具有相邻性 ,因此又称为单位距离码,而且首尾两个码组也有相邻性,它也是循环码。

格雷码有多种编码方案,表 1.3.21.3.21.3.2 是一种典型的格雷码。

从表 1.3.21.3.21.3.2 中能够看出,这种编码除了单位距离码的特点外,还有一个特点是具有反射特性,以表中所示的对称轴为界,上面和下面的编码,除了最高位互补反射 外,其余各位沿对称轴镜像对称 。利用这一特性就可以很方便的构成维数不同的格雷码。

格雷码的单位距离特性很有意义。例如,两个相邻的十进制数 131313 和 141414 对应的二进制码分别为 110111011101 和 111011101110,用二进制加 111 计数时,从 131313 变为 141414,需要改变两位,实际上两位无法同时改变,如果是最低位先置 000,然后次低位再置 111,那么中间就会出现一个短暂的错误码 110011001100,而格雷码只有一位发生了变化,则不会出现这种错误。格雷码的这种特性在很多应用上都很重要,例如轴角编码器。

二进制转格雷码 下面的规则可以将二进制转换为对应的格雷码。

(1)格雷码中最高位(最左边的位)与对应的二进制的最高位相同;

(2)从左到右,每对相邻两位二进制码位相加得到下一个格雷码,这里要舍弃进位。

例如,将二进制转 101101011010110 换成格雷码的过程如下:1−+→0−+→1−+→1−+→0二进制数↓↓↓↓↓11101格雷码\begin{array}{ll}1-+\rightarrow0-+\rightarrow1-+\rightarrow1-+\rightarrow0&二进制数\\\downarrow\kern 35pt\downarrow\kern 35pt\downarrow\kern 35pt\downarrow\kern 35pt\downarrow\\1\kern 35pt1\kern 35pt1\kern 35pt0\kern 35pt1&格雷码\end{array}1−+→0−+→1−+→1−+→0↓↓↓↓↓11101二进制数格雷码转换成的格雷码是 111011110111101.

格雷码转二进制 可以用下面的规则将格雷码转换成二进制。

(1)二进制数的最高位(最左边的位)等于格雷码的最高位;

(2)将产生的每个二进制数与下一相邻的格雷码位相加,舍弃进位,得到下一个相邻的二进制位。

例如,将格雷码 110111101111011 转换为二进制码的过程如下:

二进制的结果是 100101001010010.

2、奇偶校验码

奇偶校验码是一种能够检测出信息在传输过程中产生奇数个码元错误的代码,它是由信息位和校验位两部分组成。

信息位是位数不限的任何一种二进制代码,校验位只有一位,它可以放在信息位的前面,也可以放在信息位的后面。奇偶校验的编码方式有两种:

(1)使得一组代码中的信息位和校验位 "1" 的个数之和为奇数,称为奇校验

(2)使得一组代码中的信息位和校验位 "1" 的个数之和为偶数,称为偶校验

表 1.3.31.3.31.3.3 列出了 8421 BCD8421\,\textrm{BCD}8421BCD 码的奇偶校验码:

接收端对接收到的奇偶校验码进行检测时,只需要检查各码组中 "1" 的个数是奇数还是偶数,就能过判断代码是否出错。对于一个给定的系统来说,通常使用的是奇校验或者偶校验,而不是两者同时使用。例如,对于一个使用偶校验的系统,需要检测接收到的一组代码中 "1" 的总数是否为偶数,如果不是,则表明接收的这一组代码中出现了错误。注意:"1""1""1" 的总数是包含校验位上的 "1""1""1" ,对于偶校验来说是偶数,对于奇校验是奇数。
奇偶校验码只能够检查出奇数个位出错,它无法检查出偶数个位的错误,而且无法确定是哪一位出现了错误,因此,它并没有纠错能力。但是奇偶校验的编码简单,设备量少,而且传输过程中通常一位码元的出错概率最大,因此奇偶校验码被广泛使用。

3、循环冗余校验码(CRC)

循环冗余校验码(cyclic redundancy check:CRC)是用来检测数据在通信链路层上传输时发生一位或两位错误的一种广泛应用的编码方式。这个通信链路可以是两台联网的计算机之间的线路,也可以是数字存储设备(如 CD\textrm{CD}CD、DVD\textrm{DVD}DVD 和硬盘等)与计算机之间的线路。如果合理的设计系统,CRC\textrm{CRC}CRC 同样可以检测顺序传输的多位错误。在 CRC\textrm {CRC}CRC 中,一定数目的校验位(有时也称为校验和)附加到传输数据的末尾,在接收端会用 CRC\textrm{CRC}CRC 来检测是否有错误发生。尽管不是所有可能发生的错误都能够被检测出来,但是这已经比只有一个简单的奇偶校验位检测有效的多。
CRC\textrm{CRC}CRC 用数学来描述就是两个多项式相除,产生一个余数。多项式的数学表达是指数为正的项之和,当项前面的系数只能为 000 或 111 时,称为单变量多项式(univariate polynomial)。例如,1x3+0x2+1x1+1x01x^3+0x^2+1x^1+1x^01x3+0x2+1x1+1x0 是一个单变量多项式,可以简写为 x3+x1+x0x^3+x^1+x^0x3+x1+x0,它可以用 444 位二进制数 101110111011 来描述。大部分循环冗余校验使用的是 161616 位或更多位的多项式,但是为了简单起见,这里以 444 位来进行解释。

模 2 运算(Modulo-2 Operations): 简单来说,循环冗余校验是建立在二进制除法的基础上的;而我们知道,除法就是一系列的减法和移位的组合。为了处理减法运算,我们使用一种称为模 222 的运算。模 222 的加法(或减法)与二进制数的加法(或减法)没有多大区别,唯一的区别就是舍弃进位。模 222 运算就是加起来后对 222 取余,其真值表如下:

真值表(truth tables) 广泛应用于逻辑电路的描述。如上表所示,222 位二进制数总共有 444 种不同的组合方式,上表中的模 222 运算实质上就是异或(exclusive-OR) 运算。模 222 运算的一条简单规则就是如果两个输入不同,输出 111,否则输出 000.

CRC\textrm{CRC}CRC 校验过程如下:

(1)首先选择一个固定的生成码(generator code);它要比所要检测的代码位数要少,接收端和发送端事先都要知道这个生成码,并且两边都要相同;

(2)在数据位上附加与生成码位数相同的 000;

(3)使用模 222 运算,用带有附加位的数据除以这个生成码;

(4)如果余数为 000,则直接发生数据位和附加位;

(5)如果余数不为 000,让附加位等于余数位,这样在数据发送前可以得到余数 000;

(6)在接收端,使用模 222 运算,用接收到的带有附加位的数据除以与发送端相同的生成码;

(7)如果余数为 000,则表示没有检测到错误(在极少数情况下,也可能是多个错误相互抵消了);如果余数不为 000,表示检测到了错误,接收端可以要求发送端重新发送数据。

下图阐述了 CRC\textrm{CRC}CRC 的过程:

例8 】对下面要发送的数据 (D)(\textrm D)(D) 和生成码 (G)(\textrm G)(G),使用 CRC\textrm{CRC}CRC 来得到最终要发送的数据,并验证余数为 000。D:11010011G:1010\begin{array}{ll}\textrm D:&11010011\\\textrm G:&1010\end{array}D:G:110100111010解: 由于生成码有 444 位,因此现在数据后面加上 444 个 000,附加 000 后的数据 D′\textrm D'D′ 是 D′=110100110000\textrm D'=11010011{\color{blue}0000}D′=110100110000使用模 222 运算,用带有附加位的数据 D′\textrm D'D′ 除以生成码,直到所有的位都被用过:D′G=1101001100001010\dfrac{\textrm D'}{\textrm G}=\dfrac{11010011\color{teal}0000}{\color{red}1010}GD′=1010110100110000余数是 010001000100,因为余数不为 000,所以要在数据后面加上这 444 个余数位,得到用于发送的数据 110100110100\pmb{11010011}\color{blue}0100110100110100. 再用这个要发送的数据除以生成码,最终的余数为 000:

四、字符代码

在数字系统和计算机中,需要编码的信息除了数字外,还有字符和各种专用符号。下面介绍几种字符代码,ASCII 码是比较广泛实用的编码。

1、ASCII 码

ASCII 码是美国信息交换标准代码(American Standard Code for Information Iterchange)的英文简写,这是一个被广泛接受的的字符代码,通常用于计算机和其它电子设备上。

ASCII 码共有 128128128 个符号,这些符号是由 777 位二进制码表示。实际上,ASCII 码可以认为是 888 位码,最高位总是为 000,用十六进制表示是从 000000 一直到 7F7\textrm F7F. ASCII 码的前 323232 个字符是非图形化的命令,无法用来打印或显示,只能用于控制。例如:控制字符 "空字符(NULL)"、"换行符(line feed)"、"开始(start of text)"、"退出(escape)" 等。剩下的字符就是能够打印和显示的图形化的字符,包括字母(大小写)、十个十进制数、标点符号和一些常用的符号。

2、扩展 ASCII 符号

ASCII 码的标准符号有 128128128 个,而 IBM\textrm{IBM}IBM 又使用了另外的 128128128 个符号供他们的个人电脑使用,这种扩展的 ASCII 也用在许多其它地方,成为了非官方的标准。

扩展 ASCII 符号用十六进制的 80∼FF80\sim\textrm{FF}80∼FF 之间的 888 位码来表示,一般分为下面几组:非英语字母、外币符号、希腊字母、数学符号、绘图符号、柱状图符号和阴影符号。

3、Unicode

根据通用字符集(universal character set, UCS)给每个字符分配唯一的数值和名字,Unicode(统一码)提供了为世界上所有的书写语言的符号进行编码的能力。在计算机应用中,它可以处理多国语言、数学符号或者其它一些技术符号。

Unicode 有大量的字符集,它们多样的编码类型已经开始在很多不同的环境下取代 ASCII 码。ASCII 基本上使用的是 777 位码,而 Unicode 使用相对抽象的 "码点" ------ 非负整数 ------ 通过不同的编码形式和方案,将其映射为一个或多个字节的序列。为了保证兼容性,Unicode 将前 128128128 个码点分配成和 ASCII 码相同的字符。因此,可以认为 ASCII 是 Unicdoe 和 UCS 中的一个很小的子集。

Unicode 包含超过 10 000010\,0000100000 个字符,包含一组可以用作视觉参考的代码图表、一套编码方式、一组标准字符编码以及一套包含了上标、下标等字符特性的相关字符,还包含一系列的相关内容:如字符属性、文本标准化的规则、校对、着色、双向显示顺序(正确显示同时包含从右向左书写的文字与从左向右书写的文字,如阿拉伯文或希伯来文)等。

相关推荐
渡我白衣3 个月前
【MySQL基础】(1):MySQL的安装
大数据·数据库·人工智能·mysql·算法·计组·数电
渡我白衣3 个月前
计算机组成原理(14):算术逻辑单元ALU
大数据·人工智能·算法·机器学习·计组·数电·alu
551只玄猫3 个月前
数电实验3【译码器设计实验报告】数字电路 逻辑与计算机设计 logisim
数字电路·计算机组成原理·数电·实验报告·译码器·logisim
渡我白衣3 个月前
计算机组成原理(12):并行进位加法器
网络协议·tcp/ip·算法·信息与通信·tcpdump·计组·数电
渡我白衣4 个月前
计算机组成原理(11):加法器
python·机器学习·numpy·pandas·matplotlib·计组·数电
m0_555762904 个月前
数字电路总结
数电
渡我白衣4 个月前
计算机组成原理(10):逻辑门电路
android·人工智能·windows·嵌入式硬件·硬件工程·计组·数电
the sun345 个月前
数电基础:移位寄存器、顺序脉冲、序列信号发生器
单片机·嵌入式硬件·fpga开发·数电
the sun345 个月前
数电基础:常见的组合逻辑电路模块(2)
数电