⼆进制补码(负数编码)、反码、原码
补码是对负整数在计算机中存储的⼀种形式;
第⼆种形式的负数在计算机中可以使⽤(负号加数字)的形式表⽰⼀个负数;例如(-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)两题结果均错误,查其最⾼位和次⾼位的进位位,只有⼀位产⽣了进位。此即为判断机器是正常进位还是溢出的基本依据,在微型机中可⽤异或电路来实现上述的判断。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。