【计算机组成原理】带符号整数的表示——补码与反码

封面

导读

大家好,很高兴又和大家见面啦!!!

在上一篇内容中我们介绍了有符号整数的原码形式,有符号整数的原码表示法中,我们需要了解以下内容:

  • 机器数最高位为符号位——0为正,1为负;
  • 除最高位以外的二进制位为数值位
  • 原码形式的取值范围: − ( 2 n − 1 − 1 ) ~ 2 n − 1 − 1 -(2^{n-1}-1)~2^{n-1}-1 (2n11)2n11
  • 原码的真值0有两种形式: [ + 0 ] = 0 , 0000 [+0]=0,0000 [+0]=0,0000 [ − 0 ] = 1 , 0000 [-0]=1,0000 [0]=1,0000
  • 原码的运算过程过于复杂,不太适合直接使用原码进行运算

为了节约成本,,让有符号整数的运算变的简便,于是便有了补码的表现形式。下面我们就来认识一下有符号整数的补码;

一、补码

有符号整数在计算机中是以补码的形式进行存储,通过补码的形式,有符号整数的运算可以统一采用加法操作实现,这样即简化了操作,又节约了成本。

那什么是补码呢?

补码和原码一样,也是有符号整数的一种二进制表示形式

1.1 原码转补码

对于有符号整数而言,补码的形式有两种:

  • 正数的补码 = 正数的原码
    • 正数9的原码: [ + 9 ] 原 = 0 , 1001 [+9]_原 = 0,1001 [+9]=0,1001 其对应的补码 [ + 9 ] 补 = 0 , 1001 [+9]_补=0,1001 [+9]=0,1001
  • 负数的补码 = 正数的原码符号位不变,数值位按位取反,末位加1
    • 负数9的原码: [ − 9 ] 原 = 1 , 1001 [- 9]_原 = 1,1001 [9]=1,1001
    • 数值位按位取反得: [ − 9 ] 反 = 1 , 0110 [-9]_反 = 1,0110 [9]=1,0110
    • 末位加1,得补码: [ − 9 ] 补 = 1 , 0111 [ -9]_补=1,0111 [9]=1,0111

真值0所对应的原码有两种形式,通过补码与真值的转换规则我们能够得到真值0的两种形式的补码:

  • 正0的原码: [ + 0 ] 原 = 0 , 0000 [+0]_原 = 0,0000 [+0]=0,0000 其对应的补码 [ + 0 ] 补 = 0 , 0000 [+0]_补=0,0000 [+0]=0,0000
  • 负数9的原码: [ − 0 ] 原 = 1 , 0000 [- 0]_原 = 1,0000 [0]=1,0000
    • 数值位按位取反得: [ − 0 ] 反 = 1 , 1111 [-0]_反 = 1,1111 [0]=1,1111
    • 末位加1,得补码: [ − 0 ] 补 = 0 , 0000 [ -0]_补=0,0000 [0]=0,0000

此时我们会发现,真值0的两种原码形式所对应的补码都是 [ 0 ] 补 = 0 , 0000 [ 0]_补=0,0000 [0]=0,0000 。此时大家会不会想到什么?

有朋友已经反应过来了,既然真值0的补码只有1种形式,那么在机器数为8位的机器下 [ − x ] 补 = 1 , 0000000 [-x]_补 = 1,0000000 [x]=1,0000000 这个x是多少呢?

这里我们根据按权展开相加法可以得到: ( 1 , 0000 ) 2 = ( 128 ) 10 (1,0000)_2 = (128)_{10} (1,0000)2=(128)10 。从结果可以看到,这个 x x x 实际上表示的是真值 128 128 128,那也就是说 1 , 0000 1,0000 1,0000 其实就是真值 − 128 -128 128 所对应的补码,因此我们便可以得到一个结论:

  • 有符号整数的补码的取值范围: − 2 n − 1 ~ 2 n − 1 − 1 -2^{n-1}~2^{n-1}-1 2n12n11

从取值范围来看,有符号整数的补码的范围要大于有符号整数的原码范围,所以有符号整数的原码可以直接转换成补码,但是有符号整数的补码不一定能够转换成原码。

那补码又应该如何转换成原码呢?

1.2 补码转原码

从原码转换成补码的过程来看,只要我们逆向推导就可以成功转化,即:

  • 正数的原码 = 正数的补码
  • 负数的原码 = 负数的补码末位减1后,再数值位按位取反

理论上来讲,这样的转换是没有任何问题的,但是在实际开发过程中,减法的实现成本太高,因此,在执行补码转换成原码时,实际上采取的是与原码转换成补码相同的方式:

  • 正数的原码 = 正数的补码
  • 负数的原码 = 负数的补码符号位不变,数值位按位取反,末位加1

这里我们主要以负9为例:

  • − 9 -9 9对应的原码: [ − 9 ] 原 = 1 , 1001 [-9]_原 = 1,1001 [9]=1,1001
  • 符号位不变,数值位按位取反: 1 , 0110 1,0110 1,0110
  • 末位加1: 1 , 0111 1,0111 1,0111
  • − 9 -9 9对应的补码: [ − 9 ] 补 = 1 , 0111 [-9]_补 = 1,0111 [9]=1,0111
  • 符号位不变,数值位按位取反: 1 , 1000 1,1000 1,1000
  • 末位加1: 1 , 1001 1,1001 1,1001
  • − 9 -9 9对应的原码: [ − 9 ] 原 = 1 , 1001 [-9]_原 = 1,1001 [9]=1,1001

可以看到补码通过同样的步骤,同样可以获得原码。因此原码与补码之间的相互转换规则可以总结为:

  • 正数的原码 = 正数的补码
  • 负数的原码与补码的转换都遵循:符号位不变,数值位按位取反,末位加1

二、反码

在有符号整数的表示方法中,原码在转换到补码时,正负数的规则是不一样的:

  • 正数的补码 = 原码
  • 负数的补码 = 原码符号位不变,数值位按位取反,末位加1

那现在问题来了,如果在转化的过程中,我们不做末位加1的操作,那得到的是什么呢?

其实,所得到的这个二进制形式我们将其称为反码。反码在计算机中主要是作为一个数码变换的中间表示形式。对于有符号整数的正数而言,它的反码与原码以及补码相同,而有符号整数的负数的反码是由原码直接将数值位按位取反获得。

因此,反码与原码一样,它所能表示的数值的取值范围: − ( 2 n − 1 − 1 ) ~ 2 n − 1 − 1 -(2^{n-1}-1)~2^{n-1}-1 (2n11)2n11 ,并且在反码中真值0的表示也有两种形式:

  • 正0的反码: [ + 0 ] 反 = 0 , 0000 [+0]_反=0,0000 [+0]=0,0000
  • 负0的反码: [ − 0 ] 反 = 1 , 1111 [-0]_反=1,1111 [0]=1,1111

三、原码、补码、反码的相互转换

前面我们已经介绍了原码与补码之间的转换规则,那么反码与原码和补码又是如何进行转换的呢?

从反码的定义来看:

  • 正数的反码 = 正数的原码
  • 负数的反码 = 负数原码的符号为不变,数值位按位取反

那也就是说,反码与原码之间的转换的规则遵循:

  • 正数的反码 = 正数的原码
  • 负数的原码与反码的转换:符号位不变了,数值位按位取反

这么看来,对于有符号正数而言,其原码、反码与补码就是相同的,即:
[ x ] 原 = [ x ] 反 = [ x ] 补 , x > = 0 [x]_原=[x]_反=[x]_补,x >= 0 [x]=[x]=[x]x>=0

而对于负数而言,它们之间的关系则稍有不同。从理论上来说,负数的原反补之间满足关系:

  • 原码与反码:符号位不变,数值位按位取反
  • [ x ] 补 = [ x ] 反 + 1 [x]_补 = [x]_反 + 1 [x]=[x]+1
  • [ x ] 反 = [ x ] 补 − 1 [x]_反 = [x]_补- 1 [x]=[x]1

但是在硬件实现的过程中,补码是无法直接转换成反码的,只能通过原码来得到反码,即:

  • 补码—>原码—>反码
    • 补码符号位不变,数值位按位取反,末位加1得原码
    • 原码符号位不变,数值位按位取反得反码

结语

今天的内容到这里就全部结束了,在下一篇内容中我们将介绍《有符号整数的运算》的相关内容,大家记得关注哦!如果大家喜欢博主的内容,可以点赞、收藏加评论支持一下博主,当然也可以将博主的内容转发给你身边需要的朋友。最后感谢各位朋友的支持,咱们下一篇再见!!!

  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值