问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

深入理解计算机中的补码、反码、原码

创作时间:
作者:
@小白创作中心

深入理解计算机中的补码、反码、原码

引用
CSDN
1.
https://blog.csdn.net/xiaolingting/article/details/144879209

计算机中的补码、反码、原码是理解计算机底层原理的重要概念。本文从日常生活中的钟表计时问题引入,逐步展开对这些概念的解释,通过具体的数学推导和实例说明,帮助读者深入理解这些概念的本质和相互关系。

一、基本概念

1.0、余数(remainder)

在算术中,当两个整数相除的结果不能以整数商表示时,余数便是其“余留下的量”。当余数为零时,被称为整除。即:被除数 / 除数 = 商……余数,用数学表示:

a = qd + r, 0 <= r < d

,其中a为被除数,q为商(quotient),d为除数(divisor),r为余数(remainder)。

举例:当除数为4时,任何正数除以4时,余数总在0, 1, 2, 3中;

0 / 4 = 0 …… 0
1 / 4 = 0 …… 1
2 / 4 = 0 …… 2
3 / 4 = 1 …… 3
4 / 4 = 1 …… 0
5 / 4 = 1 …… 1
6 / 4 = 1 …… 2
7 / 4 = 1 …… 3
8 / 4 = 2 …… 0
……

如上,被除数从0开始递增时,余数会在0, 1, 2, 3中一直循环下去,这就是同余

现在我们考虑除数为10时,则余数在0~9这10个数字中出现;把这10个数字同样置于圆盘中,如上图所示。

在0-9这10个数字的圆盘中,再也不会有其它数字了,也就是我们限定了我们的数字范围为0~9,数字个数(记为模)为10。

给定圆盘上任一个数字作为起始点(记为 src),任一个数字为终止点(记为dest),我们考虑从src出发,如何到达dest,可以前进(记为 + ),可以后退(记为 - )

举例

src = 3,dest = 4;

  • 前进1步(+1),即 3 + 1 = 4;
  • 后退9步(-9), 即 3 - 9 = 4;
    src = 3,dest = 3;
  • 前进0步(+0),即 3 + 0 = 3;
  • 后退(9+1)步(-(9+1)), 即 3 - ( 9 + 1) = 4;// 因为我们限定了数字范围为0~9,所以写成(9 + 1)
    src = 5,dest = 9;
  • 前进4步(+4),即 5 + 4 = 9;
  • 后退6步(-6), 即 5 - 6 = 9;
    通过上面的例子,发现了吗?
  • 对于确定的起止点(如src = 3,dest = 4),不管前进或者后退,我们都可以到达,也就是说前进(1步)等价于后退(9步),
  • 前进步数和后退步数之和为模(10),模意味着啥?
  • 模意味着走了一圈,一个轮回,起点走一圈,又回到了起点

1.1、补数(complement)

定义:对于给定的进位制,相加后能使自然数 a 的位数增加 1 的最小的数。

说人话:就是前面前进和后退的步数等价的组合(如1和9、2和8、3和7、4和6),也即可以组成模(如10)的组合。

即:

当 a = 1时,a只有1位数字(即个位)要想将a变成2(1+1)位数字10(十位、个位),需要增加9。

所以 9是1的补数;当然1也是9的补数,即1、9互为补数;

同理:2、8互为补数;

3、7互为补数;

4、6互为补数;

问: 36的补数是多少?

答:64

根据上面定义,我们知道对于整数a,a的补数 = 模 - a(a>=0);

补数有啥用?

还是回到之前我们0~9这10个数字的圆盘上来,我们来算小学生都会的10以内的加减法:

一顿操作猛如虎,一看结果:直呼OMG,

正如上图所示:减掉一个数,等价于加上这个数的补数

这里有个重要的前提:数字是有范围的(上面我们限定了0~9这10个数字)

1.2、减法

根据我们上面的结论:当数字是有范围的,则对于这个范围内的数字,减掉一个数,等价于加上这个数的补数,我们可以用加法替代减法,进一步:减去一个正数相当于加上这个正数对应的负数。

还是回到我们前面提到的圆盘上来,我们把这条结论实践下:

  • 我们先在坐标轴上标出0~9这10个数字范围,然后移动这个范围框,使框内正负数个数大致相等,如下图所示,数字范围变成了
    -5 ~ 4
    这10个数字。
  • 将坐标轴上的数字范围同步映射到圆盘上。
  • 此时,圆盘上数字的运算可以用圆盘外相对应的数字进行替代,即圆盘上的数字范围已经改变了,由之前的0 ~ 9变成了现在的**-5 ~ 4**。

1.3、补码

看到这里,不知道你是否认可前面的推导结论?

不认可?不认可就对了。聪明的你一定发现了上面的计算的问题:

1 - 5 = -4,在我们映射后变成了1 + 5 = 6-4 不等于 6?虽然圆盘上6确实对应-4,但我们需要的是正确的结果-4,怎么将6转换成-4?

  • 好了,为了后面好叙述,我们先给实际求值结果记为原码,映射后的结果记为补码。我们先分析下实际的求值结果和映射后的结果:
  • 发现原码为0和正数时,补码正确,即原码为0和正数时,原码等于补码
  • 原码为负数时,补码错误,即原码为负数时,原码不等于补码。

问题来了?原码为负数时,补码(如6)怎么转换成原码(如-4)?

答: 谜底就在谜面上,你直接看圆盘不就好了,圆盘上都标注了,圆盘内外侧的数字就是我们原码和补码的映射表。

问题又来了?圆盘上的映射怎么来的?

答:通过补数变换得到的,即原码为负数时,补码 + |原码| = 模,也即原码为负数时,补数 + |原码| = 模,在1.1小节中,我们提到了a的补数 = 模 - a(a>=0);

综上:原码为负数时,补码 + |原码| = 模

二、 二进制里的花花世界

宏观世界搞定了,看看微观世界,十进制搞完了,看看二进制。

二进制我们以1Byte(8bit)研究,1 Byte 可以表示256个数(28),即模为256

2.1 原码

1 Byte 范围的内数字为0~255这256个数字。将其置于圆盘上如下:

2.2 补码

  • 调整数字范围使其映射到**-128~127256**个数字:
  • 调整圆盘范围,即原码写到圆盘上,补码写到圆盘外,如下:

2.3 补码和原码转换

原码和补码怎么转换呢?

通过1.3节,我们知道如下结论:

  • 原码为0和正数时,原码等于补码
  • 原码为负数时,补码 + |原码| = 模

  • 还记得我们在1.3 小节 文末得到的结论吗?原码为负数时,补码 + |原码| = 模,我们变换下这个等式,即原码为负数时,补码 = 模 - |原码|,按照公式我们计算下:

至此,二进制的原码和补码转换我们也已搞定,即:

  • 原码为0和正数时,原码等于补码
  • 原码为负数时,补码 = 模 - |原码|

2.4 反码

不知道你绕晕了吗?还记得我们的初心吗?怎么用加法替代减法?

2.3 节说原码为负数时,补码 = 模 - |原码|,这玩呢?前面这么多推理就是想用加法替代减法,结果搞了半天回到了原点,还使得计算减法,自己替代自己吗?替代了个寂寞……

不急,稍安勿躁,且听下面道来。

2.4.1 模

细想下:补数的定义,使得当前数的位数增加1位

  • 假设二进制下,当前为8位,问要使得增加的数最小时,怎么才能使得位数增加1位呢,即由原来的8位变成9位?
    答:增加的数为1时最小,此时当前8位数达到了最大,那就是0b 1111 1111,即0b 1111 1111+0b 0000 0001=0b 1 0000 0000
  • 所以我们找到了二进制8位数即将跳变成9位的临界值,即当前8位数的最大值0b 1111 1111;
  • 二进制时,一个数变成最大的最快方式,当然是加上该数按位取反后的值。即0b 1111 1111-0b 0000 0001=0b 1111 1110,看到了吗,0b 1111 1110正好等于0b 0000 0001按位取反的值,那就叫它反码吧,即原码为负数时,反码为原码数据位按位取反,注意这里是数据位,最高位为符号位“为使得定义一致和完整,我们补充:原码为0和正数时,原码等于反码

  • 我们来求下
  • 如上图所示,原码为负数时,模 (256) = 8bit最大值 + 1 , 8bit最大值 = 原码的绝对值 + 反码,结合之前的**原码为负数时,补码 = 模 - |原码|**得到:

至此,1 Byte 的数据我们通过补码的形式用加法替代了减法。计算机语言内的整数类型比如java的int (4Byte)、long(8Byte)都是如此。

三、总结

为了使用加法替代减法,我们先后引入了补数、模、原码、补码、反码等概念:

  • 圆盘代表数字是有范围的,该范围的大小即为,并且会首尾相连。计算机1 Byte、4Byte、8Byte天然会限定数据的范围。数据范围限定后,数据一直累计下去一定会产生数据溢出(即进位丢失),从而结束当前轮回,开始下一轮回;
  • 圆盘内的数字是原码,圆盘外的数字是补码,补码也是内的无符号整数。注意,反码 + 1只是求得补码的一种方式,并非补码的定义;
  • 原码为0和正数时,原码等于反码等于补码;
  • 原码为负数时,反码为原码数据位按位取反。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号