反码、补码的进化史(深度理解反码及补码)

本文探讨了计算机底层的机器数概念,解释了为何需要反码和补码,以及它们如何简化加减运算。重点介绍了模N加减法,展示了补码在解决正负数表示和运算效率上的优势。
摘要由CSDN通过智能技术生成

最近有了一个小问题,写篇博客记录一下,希望能帮助到更多人

💬:原码才是我们人类可以识别并用于直接计算的表示方式,那为什么还会有反码和补码?为什么用补码存储呢?

📣前言

在解决这些问题前,我们先来了解计算机的底层概念,我们人脑可以很轻松的知道机器数的第一位是符号位,但对于计算机基础电路设计来说判别第一位是符号位是非常难和复杂的事情,为了让计算机底层设计更加简单,人们开始探索将符号位参与运算,并且采用只保留加法的方法,我们知道减去一个数,等于加上这个数的负数,即:1-1 = 1 + (-1) = 0,这样让计算机运算就更加简单了,并且也让符号位参与到运算中,而且从数学角度,减法是可以转换成加法运算的。乘法同样可以转换成加法运算,除法可以转换成乘法运算,所以一切的运算都可以以加法运算为基础,这样计算机只保留了加法运算。

但是随着时代的发展和进步。如果计算机只会做加法,对于有些计算来说速度就会慢下来,这也是我们不能忍受的。所以人们会给计算机按照原理设计乘法有关的运算电路。甚至还有更加复杂的数学电路,软件(驱动)来辅助硬件来完成更多的功能。

先浅浅的认识一下机器数和真值:

机器数:

一个数在计算机中的二进制表示形式,叫做这个数的机器数,机器数是带符号的,在计算机中用一个数的最高位存放符号,正数为0,负数为1,比如,十进制中的+3,假设计算机字长为8位,转换成二进制就是0000 0011,如果是-3,就是1000 0011.那么,这里0000 0011和1000 0011就是机器数,

真值:

因为第一位为符号位,所以机器数的形式值就不等于真正的数值,例如上面的有符号数1000 0011,其最高位1代表负,其真正数值是-3,而不是形式值131(1000 0011转换成10进制等于131),所以为了区别起见,将带符号的机器数对应的真正数值称为机器数的真值。例如:0000 0001的真值=+000 0001=+1,1000 0001的真值=-000 0001=-1

举个例子

942a1005c550968c15f27aed88cc13d5.png

结论:如果用原码表示,让符号位也参与计算,对于减法来说,结果是不正确的。这也是计算机内部在存储数据时不使用原码的原因,为了解决这一问题,出现了反码。

反码:

674c77f45a1b2f705d7fc9cdb31f4605.png

使用反码计算时应该注意一点:

使用反码计算时得到的是反码,应该转换为原码后,再进行进制转换,才得到正确结果,补码也一样。举得这个例子虽然发生了进位,但最高位进位后会发生截断,所以符号位还是0。

总结反码如下缺陷:

  1. 由于溢出导致进位,所以反码本身存在"编码重复性",即存在多个编码对应一个值(就比如举例中的10,可以用1 00000000 00000000 00000000 00001001表示,也可以用00000000 00000000 00000000 00001010表示)

  1. 0这个特殊值,人们认为0是不带符号的,所以-0是没有意义的,但-0也存在编码,出现了两个编码表示0,这个也属于"编码重复性"问题

  1. 反码减法的算法规则比较复杂,需要增加计算机内部逻辑组件额外判断溢位,会影响计算效率。

补码:

补码的出现解决了反码编码重复性和运算复杂的问题

289c68fb5a0115ed39666c15e2ac6412.png

相对于反码,补码运算更简单,直接丢弃溢位,不需要针对溢位单独处理,所以用补码做运算效率高。虽然补码运算过程很简单,但是转换和运算规则却很难理解,要弄明白其中的原理,就需要揭开补码背后的数学奥秘。

普通的算数加减法:

f6c8999a0e0f22224dc7e3119d9906e6.png

普通的算数加减法是一维运算,通过向左右移动实现,比如2-3,就是以2为基点,向左移动3个单位,向左和向右是没有尽头的,可以一直移动到正的无穷大或者负的无穷大。普通算术加减法简单直观,很容易被人理解。但是对于计算机要实现算术加减法,既要区分正负数,又要分别实现加减法,设计就会很复杂,效率会很低,所以这套算术加减法并不适用计算机。所以需要找到一种不需要区分正负数就可以实现加减法转换的规则,那么计算机运行效率就会最高。

先浅浅的认识一下模和补数:

计算机中以有限的二进制位来表示数据,假定参加运算的数为n位二进制数,共能表示2的n次方个不同的数据,其模便为2的n次方。一般的,假定M为模,若数a和b满足a+b=M,则称a,b互为补数。

模N加减法:

模N加减法正是不需要区分正负数就可以实现加减法转换的运算方式,不同于普通算术加减法,它是二维运算,要理解模N加减法比较困难,可以先用生活最典型的时钟举例,

4661fc75e3ba3e9d96e89df60a1dc578.png

⏰现规定时间从零点开始,转过12个小时后又回到了零点,如果当前时间指向8点,要想知道6个小时之后的时间,就需要把时针顺时针旋转6个格,要想知道6个小时之前的时间,就需要把时针逆时针转6个格,钟顺时针相当于时间向前走,逆时针相当于时间往后走,但是时钟不会指向无穷大的数,当转过12个小时又回到了原点。

所以任意逆时针旋转得到的结果都能通过顺时钟旋转得到,当逆时针旋转N个小时,与顺时针旋转12-N小时相等,12又称为模,如果把顺时针看成是加法,逆时针看成是减法,那么时钟旋转可以看成模12的加减法运算,满足公式A-m=A+(12-m),即在时钟任一时刻A点,从A点逆时针旋转m个小时得到的结果,与从A点顺时针旋转12-m得到的结果一致,+12相当于时针拨了一圈,并不影响结果,但是却可以将减法转换为加法。有的同学可能会有疑问,12-m不还是减法嘛,是的,但是这种减法不需要减法器即可实现。12-m称为-m的补数,计算一个数的补数,并不需要减法。模N运算将减法转换成了加法。

📖 时钟讲解完成后我们再讲讲有关进制的转换,计算机使用的二进制位数是有限的,4位、8位、16位······,超出这个限制,数据会发生溢出而重新归零,这是不是和时钟很像。

我们以4位的二进制为例,讲讲补码的进化史:

首先,4位二进制数范围是0000到1111,超过1111发生进位溢出变成0000,我们可以将0000到1111看成一个圈,转一圈需要走16个格,所以模为16。举个例子,将减法转换为加法,比如计算9-5,根据公式A-m=A+(16-m),公式右边就可以写成 9+(16-5)=9+11,不难发现5和11互为补数,那么我们计算9-5就可以转换为9+11了,那么补数怎么求呢?16-9,但16在4位二进制数中无法表示,我们将16-9看成15-9+1,15的二进制为1111,15-9 --> 1111-1001=0110,0110就是9的反码,再+1,就是9的补码,这样就能将减法转换为算负数的补数,再转换为加法的运算了。

模N加减法实现了「化减为加」,但是还有个问题,没有区分正负数。人们在计算时是需要考虑正负数的,所以就需要人为的将一部分二进制划分为负数,一部分二进制划分为正数。当模M=16时,根据公式A-B=A+16-B,当A为零点时,-B=16-B,即时针逆时针移动B,也可以由顺时针移动16-B得到。零点A可以是0000到1111中的任意一个数,为了方便计算,人为规定0000为零点,那么0001为+1,1111为-1,1110为-2,以此类推,但是1000比较特殊,0000逆时针旋转8个数得到1000,所以1000为-8,相应的顺时针旋转8个数也得到了1000,1000既能表示-8又能表示+8,为了不产生冲突,人为规定1000为-8。具体表示如下图:

8945caf002c90144433444e3d6898523.png

使用补码的意义

在计算机系统中,数值一律用补码来表示和存储的,原因在于,使用补码,可以将符号位和数字域统一处理;加法和减法可以统一处理(CPU只有加法)。

此外,原码和补码的相互转换,其运算过程是相同的,不需要额外的硬件电路。(原码和补码之间的转换均可通过 取反 加一 得到,如下图,大家可以试验一下哦)

9da331a42a4f426b843e90cbbdafcaaf.png

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬羊咩咩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值