> 文档中心 > 正确的理解计算机原码,反码和补码(颠覆你的原有认知)

正确的理解计算机原码,反码和补码(颠覆你的原有认知)


首先介绍几个计算机常见的概念

机器数

机器数是一个数在计算机中的二进制表示形式。机器数分为有符号数和无符号数,我们通常所说的数在计算机中是一个字节,即8位二进制数。计算机中无符号数没有原码、反码补码。因为, 无符号数在计算机中直接将数字化成二进制然后存储在对应的存储器或者寄存器中。 这时寄存器或者存储器的位数就可以表示数值的范围,通常情况下如果是 8 位的, 表示的范围为 0 ~ 255。它的原码、反码和补码是一样的,所以无符号数不考虑原码,反码和补码。下文我们要说的是有符号数。

真值

真值就是有符号数对应的真正数值,个人理解就是用正负号来代替符号位来表示机器数 例如:

机器数 0000 0010 的真值为 +000 0010 也就是+2机器数 1000 0010 的真值为 -000 0010 也就是-2

在介绍原码,反码和补码之前请大家明白计算机在进行计算时只有加法这一种计算规则,减法乘法除法在计算机世界中本质都是加法。

原码

正是因为有了符号数,所以为了表示有符号数的正负才有了原码。0代表正,1代表负。

img

这种使用原码来存储机器数的方式,利于我们人类,却不适用于计算机。

因为计算机如果求解原码形式的(+1)和(-1)相加,得到的结果是0001(1)+1001(-1)=1010 (-2)。

并不是0,另外可以看到图中有一个(+0)和(-0),但我们的常识是0是不分正负的。

反码

为了解决正数和负数相加不等于0这个问题,在原码的基础上,反码诞生了!

“反码”表示方式是用来处理负数的,符号位置不变,其余位置相反。

img

当“原码”变成“反码”时,成功的解决了“正负相加不等于0”的问题。

过去的(+1)和(-1)相加,变成了0001+1101=1111,刚好反码表示方式中,1111象征-0。

但是这里反码仍然有两个0一个+0一个-0。

补码

为了解决两个0这个问题,补码诞生了!

在介绍补码之前,补充一个概念:

为什么要讲模这个概念呢?

因为计算机只会做加法运算,不会减法,所以计算机在做减法运算时相等于加上一个负数。

那么如何把减法化为加法呢?

想象一下日常使用的钟表,它可以显示0~12点的时间,假设现在是2点钟,请用手动拨动时针的方式将时间减4小时,有几种方式呢?

有两种方式:

  1. 逆时针将时针拨4小时

  2. 顺时针将时针拨8(12-4)小时

这里要讲的是第二种方式,为什么顺时针拨12-4也可以达到和正常思维的第一种方式一样的位置。

12就是模。

同样的,如果是十进制的两位数,80-10 和 80+90在不考虑百位数的基础上都是70。这里的90就是100-10得来的,这种情况下100就是模。

模就好比是一个极限数,在它的范围内,两个相加等于模的数互为补数,还是举100的例子

比如25和75就互为补数。

通过模我们可以得到一个数的补数,那么就可以把减法运算化为加法运算。

比如“X-Y”的减法变更为“X+Y的补数“的加法,当然前提是不考虑百位数

但是这个补数有一个不对的地方,就是如果结果是负数的情况。

比如10-90,结果应该是-80,但如果按照10+(100-90),结果是20。

20和-80明显不是一个数,怎么办呢?

当初的那些先贤们想出来的办法很简单,就是把这两个数直接划上等号,正好顺便解决了负数的表达方式。再来仔细看看这两个数的关系:-80绝对值的补数就正好是20。

所以在计算机世界中,负数的表达方式就是它绝对值的补数在计算机中的表达方式!

但是负数的表达方式是它绝对值的补数在计算机中的表达方式,这样就有了同一个数可以表达一个正数和一个负数。比如上面的20即表示正数20又表示负数-80,那我们怎么知道表达的到底是哪一个呢?

为了解决这个问题,需要给这套规则划定一个范围,原来是0~99的正数,现在既然要有部分正数需要去表示负数,那就要规定一个范围来使得一个数只代表一个含义,正好一人一半,0~49这个区间就代表正数,50~99的区间就用来代表各自补数的负值,例:98就代表-2。

那么知道了补数的概念后,我们回到计算机世界,8位二进制数一共可以表示2的8次方,256个数,即0~255 (别忘了0也要占一位的),他们的极限就是256,所以256是8位二进制数的模 。

因为计算机只能识别二进制数据所以下文都用二进制来说明,8位二进制能表示的数的极限是1 1 1 1 1 1 1 1, 就是255,在这基础上加0 0 0 0 0 0 0 1,出现了进一位 即 1 0 0 0 0 0 0 0 0。

这个1 0 0 0 0 0 0 0 0就是8位二进制数的模=256。

用我们上面了解的原理去表示正数和负数,256中一半的数0~127,代表其正数本身,另一半的数 128~255,代表其补数的负值,即“-1~-128”的区间。这就是1代表负号的由来,因为需要一半的数表示负数。

而 “X-Y”的减法 就用 “X+Y的补数” 的加法来表示。 唯一需要注意的事情是任何计算的输入值和输出结果值都需要严格遵守-128~127的范围,一旦溢出就会报错。

这也就是我们在编程里强调的为什么 byte+byte还得是byte,int+int还得是int,数据溢出问题也是每一个程序员都需要注意的问题。

所以以我们人类的思维方式想要用加法表示减法可以使用补数这个概念,但是我们求补数这个过程就用到了减法,而计算机又不会减法,这样就进入了一个死胡同:想用加法表示减法需要先用到减法。

但是奈何我们计算机大佬厉害,他们为了表示补数,发现了原码进行取反+1之后的码的真值就是这个数的补数!补数的表示形式就是补码。所以补码的意思我的理解就是补数的码,而不是取反加1码,取反+1只是计算机用来求补码的计算方式

img

至此,我们终于知道了补码的概念。

总结:

因为正数的补码和原码相同,所以就不介绍如何求正数的补码了。

负数的补码的计算方式以我们人的逻辑就是它绝对值的补数在计算机中的表达方式。

而以计算机的逻辑它绝对值的补数的求法就是这个负数的绝对值的原码进行取反+1操作。因为计算机不会减法运算。所以负数的补码的计算方式就是它绝对值的补码再取反+1。

而给出一个补码想要知道真值多少。如果是正数可以直接换算得出,负数就先进行取反+1操作,这时补码为其绝对值的补码。

一句话总结就是正数的补码取反+1后为其对应负数的补码;负数的补码取反+1后,为其绝对值

刚开始写博客,如果觉得内容对您有用,希望您可以点个赞支持一下,十分感谢!如果有不对的地方您可以指出,我会及时更改。

开发者涨薪指南 正确的理解计算机原码,反码和补码(颠覆你的原有认知) 48位大咖的思考法则、工作方式、逻辑体系