谈谈我眼中的补码

版权声明:本文版权归CSDN作者“领章”所有,欢迎转载,但必须保留此段声明,且在文章页面明显位置给出原文链接。 https://blog.csdn.net/JWbonze/article/details/85591738

导读:补码是如何产生的、计算机如何表示负数。

1.前提认知

(1)计算机中只有加法器,加减法使用的都是加法器,同时计算机通过加法器左移累加实现乘法运算、右移累减实现除法运算。

(2)补码是一种编码格式,它不是真实的数字。

我在之前的文章《从晶体管开始聊聊计算机为什么采用二进制》中说过计算机中所有机器码“0101”实际上是高低电平的不同排列组合。

至于这些“0101”数字真正表示的是什么人类可读的信息,是由计算机科学家制定的标准决定的。

这个标准就是我们常说的“编码格式”或“编码规则”,比如“0000_0001”在某种标准下表示现实世界十进制1,但是在另一种标准下可以表示汉字“我”,在另一种标准下表示“A”。

所以,学习原码、补码时不要认为它们是数字,它们并没有表示实际大小的意义。

(3)如下约定:“49-9=40”这个等式中49是被减数,9是减数。

2.补码的实质

2.1.补码的引入

假如我们面对的是一台十进制的2bit计算机,即这个计算机最多能存储两位数。

(1)那么如何让9变为0?

第一种方式是9-9,得数为0;

第二种方式是9+91,得数也为0。因为9+91=100,而2bit的计算机无法记录百位数1,所以得到0。

从这里可以发现一个规律,对于2bit的计算机来说,-9的计算效果相当于+91。

下面是对“49-9”按照这种计算效果进行计算:

49-9

=49+91

=140

因为3bit的140超出存储空间,所以要舍去百位的1,得数为40,即49-9=40。

(2)同样一台十进制的2bit计算机,我们可以计算一下“30-20”。

对于“20”这个数字来说,它要想变为0,要么减去20,要么加上80,所以“-20”的计算效果与“+80”相同。

接下来计算一下30-20:

30-20

=30+80

=110

舍去最高位1,得数10,即30-20等于10。

从上面的这两个例子就可以看出对于一台十进制的2bit计算机来说,减法可以通过加法来实现。

这里产生两个问题:(1)“减数”和替换它的“加数”之间有什么样的对应关系,即如何根据减数确定加数;

(2)为什么减法可以使用加法替代。

2.2.加数是减数的补码

对于“49-9=49+91”而言,减数9加上91正好为100,同样“30-20=30+80”中减数20加上80也是100。

这不是巧合,而是一种计算方式。

对于一台十进制的2bit计算机,这里面和减数一起加起来得到100的那个数就是减数的“补码”,减法计算其实就是加上那个减数的补码。

2.3.为什么减法可以使用加法替代

在回答这个问题之前,先搞清楚对于一台十进制的2bit计算机,为什么要以100为补码计算的标准呢?

原因很简单,因为2bit计算机只能存储2位数,100这个3bit数字实际上就是00,数字当加到100时,自动减少100。

换句话说,对于2bit的十进制计算机来说,遇见100就清零,我这里简记为“遇百变零”,这就是一个减法,只不过是一次就固定的减100。

计算机可以借助这个特性实现减法。

比如“30-20”是在30的基础上减掉20,我们“遇百变零”是减100,而此处只要减去20,多减去100,那么我们就加上80。

所以“30-20=30+80”。

这就是为什么减法可以使用加法替代。

进而也可以认识到,减数与其补码两个数相加之和会将所有位数清零。

2.4.减数补码的计算

上面已经说过:减数与其补码两个数相加之和会将计算机所有位数清零。

这就是减数的补码的计算方式。

对于十进制计算机来说,2bit计算机,减数 1的补码就是99;4bit计算机,减数1的补码是9999。

对于二进制计算机来说,2bit计算机,减数01的补码就是11;4bit计算机,减数0001的补码就是1111.

到了这里,我们用二进制验证一下,4bit计算机计算4-3。

3的二进制是0011,3作为减数,所以要变为补码与4相加,那么我们先计算一下0011的补码,如下表。

减数

 

0

0

1

1

补码

 

1

1

0

1

清零

1

0

0

0

0

减数的二进制数与其补码之和会将4bit清零,可以看出0011的补码是1101,也就是减数3参与加法器计算时使用的是“1101”编码。

所以“4-3”在计算机内就是“0100+1101”,结果为10001,最高位无法存储、舍去,结果为0001,如下表。

4的补码

 

0

1

0

0

-3的补码

 

1

1

0

1

1

0

0

0

1

即4-3的计算结果为0001,转换为十进制,就是1。

到这里,我们暂停,先回忆一下:计算机内的减法计算实质上是被减数加上减数的补码。比如49-9=49+91=40.

对于N位(bit)计算机而言,一个减数与其补码之和可以使N位清零。

减数就是我们现实生活中人类可读的数字,补码是计算机识别的编码符号。

由减数转化为补码这个过程称为编码,如实际数字-9转换为补码91就是编码;

由补码转换为减数这个过程称为解码,如补码91转换为实际数字-9就是解码。

3.补码如何表示负数

本篇文章的两个知识点,补码的计算已经说完了。

下面说下一个知识点,补码表示负数的规律。

3.1.补码一分为二

因为计算机内没有减号、负号,科学家为了表示负数,就将数字区间一分为二,一半表示正数,另一半表示负数。

同样以十进制的2bit计算机作为说明,2bit计算机能够存储00到99一共100个数字。

不对!应该是00到99一共100个补码。

计算机识别的不是人类可读信息,而是这些可读信息转换的编码,一定要有这种认知!

科学家将00到49这50个补码作为正数,而且和实际数字一一对应,比如00表示实际的0,49对应实际的49。

之后将50到99这50个补码作为负数,但不是50表示实际数字-1,而是99表示实际数字的-1,50表示实际数字-50。

负数和补码之间之所以采用这种映射方式,还是因为“补码”这种编码格式:负数的绝对值(也就是减法中的减数)与其补码之和会使计算机所有位数清零。

比如-1的补码就是99,-50的补码是50。

反过来想(也就是解码),补码99表示实际数字-1,补码50表示实际数字-50.

总之,不论编码还是解码,使用的都是补码的规则:负数绝对值与补码之和清零所有位。

到这里你可能想明白了为什么8bit二进制计算机内补码1111_1111表示-1,为什么补码1000_0000是最大负数-128而不是-0了吧。

这样一来,00到99这100个补码就表示了实际数字-50到49。

二进制计算机也是如此,比如8bit计算机共有0000_0000到1111_1111一共256个补码。

256个补码一分为二,0000_0000到0111_1111共计128个补码表示正数,而且和实际数字一一对应。

比如补码0000_0000表示实际数字0,0000_1000表示实际数字8,0111_1111表示实际数字127.

1000_0000到1111_1111共计128个补码表示负数,和实际负数之间采用补码这种映射关系。

比如补码1111_1111表示-1,因为1111_1111加上0000_0001清零;补码1000_0000表示-128,因为1000_0000加上1000_0000清零。

如此一来,8bit二进制计算机就可以表示-128到127这些实际大小的数字了。

在计算机中,8位带符号二进制数的取值范围是[-128, 127],比如Java中byte类型。

这与我们上面的解释对应上了。

同时也澄清了一个误会,计算机最高位1表示负数,是因为1000_0000将256个补码恰好一分为二,用1000_0000及以后的补码表示负数。

计算机对于最高位是1的数字并不是将首位1直接变为负号,而是通过补码这种编码将其整体解码为负数。

所以不要将最高位的1与其它位的二进制数分离开来,分别看待。

3.2.补码的解码

在之前的案例中,我们实现减法都是大数减去小数,如49-9,3-20,4-3.但是如果换成小数减去大数,好像就出问题了。

如果你没有发现可以计算一下“9-49”。

9-49

=9+51

=60

竟然出现了“9-49=9+51=60”的情况?

9-49应该等于-40,怎么是60呢?

原因很简单,60是-40的补码。

计算机只识别补码60,之后就会解码将其转化为实际数字-40。

这时你可能想到了文章开篇说的一种认知——补码只是一种编码格式,它不是表示真正大小的数字。

此时60这个编码对应的实际数字就是-40,即9-49=-40。

到了这里,我们就了解了人类是如何给计算机赋予负号的含义。就是通过补码的编码与解码。

4.总结

4.1.运算数据都是补码形式

人类输入的运算信息在计算机中是以补码的形式存在的。不论是加法中的加数,还是减法中的被减数、减数,还是运算结果。

你可能想到了“49-9=49+91=40”中的“40”其实也是补码,只不过形式上和实际数字相同。

4.2.减法的执行过程

(1)减法中的被减数和减数首先按照补码这种编码格式转换为补码,被减数和补码从形式上看一模一样,减数则是与其补码之和清零。

(2)加法器执行加法。

(3)如果数据溢出,那么就将剩下的数据解码为实际数字;如果没有溢出,就将这个结果解码为实际数字。

以十进制2bit计算机为例,49-9转换为补码49和91,之后加法器相加,溢出一位得到补码40,解码为实际数字40;

9-49转换为补码是9和51,之后加法器相加,没有溢出得到补码60,解码为实际数字-40。

以上就是我对补码的初步认识。

猜你喜欢

转载自blog.csdn.net/JWbonze/article/details/85591738