前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >计算机基础(4)——原码、补码、反码

计算机基础(4)——原码、补码、反码

原创
作者头像
绿水长流z
修改2025-01-03 17:25:30
修改2025-01-03 17:25:30
15200
代码可运行
举报
文章被收录于专栏:计算机基础计算机基础
运行总次数:0
代码可运行

1.5 原码、反码、补码

计算机为了区分数值的正负提出了符号位的设定,计算机用最高位存放符号,这个被称为符号位。正数的符号位为0, 负数的符号位为1。

例如,1的二进制表示形式为0000 0001,而-1的二进制表示形式为1000 0001。在计算机中,一个字节为8个位,最大值为0111 1111,十进制为127。最小值为1000 0000,十进制为-128。因此一个字节的取值范围为-128~127之间。

1.5.1 原码

原码是最直观的表示方法,它直接将数值转换为二进制数,是十进制数在二进制中的体现,该二进制包含符号位。原码就是我们之前使用的二进制的格式,只不过我们之前一直没有使用二进制描述过负数,使用原码描述负数只要将符号位设定为1即可。

但仅仅存在原码对于计算机进行运算时有着巨大缺陷;那就是对于负数的计算。

  • 对于正数的计算,原码不会有问题,例如计算2+6:
代码语言:javascript
代码运行次数:0
运行
复制
  0000 0010
+ 0000 0110
-----------------
  0000 1000

0000 1000的十进制为8,计算正确。

  • 对于负数的运算,发现结果与目标值不对,例如计算2+(-6):
代码语言:javascript
代码运行次数:0
运行
复制
  0000 0011 (2)
+ 1000 0110 (-6)
--------------
  1000 1001

1000 1001的十进制为-9,计算错误。

为了解决原码不能用于计算负数的这种问题,因此迫切需要一种新的表示方法来解决这个巨大的缺陷,于是反码出现了。

Tips:有些人在这里肯定会有一个疑问,为什么要计算2+(-6),而不是2-6这样的操作呢?这是因为CPU中只设计了加法器,没有所谓的“减法器”,因此2-6只能看做成2+(-6)这样的操作。

1.5.2 反码

反码提供了一种便捷的方法来执行减法操作,这样的设计允许CPU利用已有的加法逻辑来完成减法运算,无需额外的减法器硬件,从而简化了处理器的设计并减少了硬件资源的需求。

1. 反码的转换规则

有了原码之后我们可以根据规则转换成对应的反码,其规则如下:

  • 正数的反码:原码本身。
  • 负数的反码:原码的符号位不变,其余位取反。

一些数的原码、反码的表示如表所示。

十进制数字

原码

反码

1

0000 0001

0000 0001

-1

1000 0001

1111 1110

2

0000 0010

0000 0010

-2

1000 0010

1111 1101

原码转换为反码后,使用反码来进行计算。对于通常的负数计算,使用反码可以完成,例如我们计算2-6。

2的原码为0000 0010,反码为0000 0010。-6的原码为1000 0110,反码为1111 1001,计算如下:

代码语言:javascript
代码运行次数:0
运行
复制
  0000 0010 (2)
+ 1111 1001 (-6)
-----------
  1111 1011 (-4反码)
  1000 0100 (-4原码)

上述案例的计算结果为:1111 1011(反码),转换为原码为:1000 0100,结果为-4,刚好是正确的。

2. 反码的进位

需要注意的是,使用反码计算时,高位进位时需要作用到低位。例如我们换一个数进行计算,计算-4+(-1)。

-4的原码为1000 0100,反码为1111 1011。-1的原码为1000 0001,反码为1111 1110,计算如下:

代码语言:javascript
代码运行次数:0
运行
复制
  1111 1011 (-4)
+ 1111 1110 (-1)
-----------
  1111 1001 (-6)
          1 (高位进位之后作用到低位,在低位进1位)
-----------
  1111 1010 (-5反码)
  1000 0101 (-5原码)
3. 反码的缺陷

反码也有它的缺陷,那就是计算结果为0时。

我们来计算2+(-2),-2的原码为:1000 0010,反码为:1111 1101。

代码语言:javascript
代码运行次数:0
运行
复制
  0000 0010 (2)
+ 1111 1101 (-2)
-----------------
  1111 1111 (反码)
  1000 0000 (原码)

上述案例计算的结果为1111 1111转回原码为1000 0000,结果为-0。那么问题来了,-0是0吗?在二进制中出现了两个可以描述“0”这个数值的二进制,一个为1000 0000,另一个为0000 0000,“0”这个数字在计算机中的编码就不是唯一的了,这很显然有问题。

1.5.3 补码

使用反码表示零时存在两种形式(+0和-0),这在逻辑上不严谨。计算机科学家们意识到这个问题后决定,把0当成正数,即“+0”,也就是0000 0000,此时八位二进制表示的正数范围为:+0到+127。对负数做调整,不能使用1111 1111来表示“-0”,因为不存在“-0”这个数。

1111 1111既然不表示“-0”,也就意味着可以表示其他的数值,因而八位二进制能够表述的数字又多了一位。那如何利用这一位数值呢?我们把基于反码的八位二进制表示的负数整体“向后挪动1位”,负数的取值范围就从-0到-127变为-1到-128。1111 1111不再表示-0了,而是表示-1,以此类推1111 1110表述的就是-2。

那么如何只对负数整体“向后挪动1位”呢?那就是对一个数的反码进行+1操作,如下:

  • 1111 1110(-1的反码)+1就是1111 1111,这样1111 1111就不再表示-0而是表示-1。
  • 1111 1101(-2的反码)+1就是1111 1110,这样1111 1110就不再表示-1而是表示-2。

就这样,八位二进制数的最小取值范围从-0到127变为了-1到-128。这种基于反码+1的操作就是补码。

1. 补码的转换规则

计算机在进行运算时,先将原码转回为对应的补码。其转换规则如下:

  • 正数的补码:原码本身,正数的原码、反码、补码全都一致。
  • 负数的补码:原码的反码+1。

一些数的原码、反码、补码的表示如表所示。

十进制数字

原码

反码

补码

1

0000 0001

0000 0001

0000 0001

-1

1000 0001

1111 1110

1111 1111

2

0000 0010

0000 0010

0000 0010

-2

1000 0010

1111 1101

1111 1110

127

0111 1111

0111 1111

0111 1111

-127

1111 1111

1000 0000

1000 0001

-128

超出表示范围

超出表示范围

10000000

因为补码把“-0”这个位置利用起来了,所以在一个字节下的补码还可以记录一个特殊的值:-128,这个数据在1个字节下是没有原码和反码的。

2. 使用补码计算0

我们使用补码再来计算2+(-2)。

-2的补码为1111 1110。2的原码、反码、补码都为本身,即:0000 0010。计算过程如下:

代码语言:javascript
代码运行次数:0
运行
复制
  1111 1110 (-2)
+ 0000 0010 (2)
------------
  0000 0000 (0)

可以看到,上述的计算结果为0。补码很好的解决了反码相加结果为0的问题。

Tips:计算机底层存储数据时普遍使用补码形式。补码不仅能够表示正数和负数,还能够让加法和减法运算统一处理,简化了计算流程,并且能够自然地处理溢出情况。在现代计算机体系结构中,无论是整数还是浮点数,通常都采用补码表示法进行存储和运算。因此,无论是内存中的数据存储还是处理器进行的计算,补码都是被广泛采用的表示方法。

3. 补码的注意事项

八位二进制数的取值范围为:-128到+127,那如果计算的结果超出了这个范围又当如何呢?我们思考一个问题:127+1=?。

127的补码为0111 1111,1的补码:0000 0001,计算如下:

代码语言:javascript
代码运行次数:0
运行
复制
  0111 1111 (127)
+ 0000 0001 (1)
-------------
  1000 0000 (-128)

正常来说127+1的结果为128,1个字节的取值范围为-128到127,并不能存储128,因而在1个字节内进行127+1的结果为-128。

不仅127+1=-128,另外-128-1的结果也会发生改变。

-128的补码:1000 0000,-1的补码:1111 1111,相加的运算结果如下:

代码语言:javascript
代码运行次数:0
运行
复制
  1000 0000 (-128)
+ 1111 1111 (-1)
-------------
  111 1111 (127)

上述代码最终计算的结果为127。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.5 原码、反码、补码
    • 1.5.1 原码
    • 1.5.2 反码
      • 1. 反码的转换规则
      • 2. 反码的进位
      • 3. 反码的缺陷
    • 1.5.3 补码
      • 1. 补码的转换规则
      • 2. 使用补码计算0
      • 3. 补码的注意事项
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档