Hi,我是小余。 本文已收录到 GitHub Androider-Planet 中。这儿有 Android 进阶成长知识体系,重视大众号 [小余的自习室] ,在成功的路上不走失!

浅谈

怎么证明你是一个真实的程序员

计算机组成原理系列(一):浅谈计算机中的“补码”

如果你看不懂这个图片里边的意思,没关系,不妨先看下文章再回过头来看这个图片,你就懂了。

机器数和真值

机器数

一个数在核算中的二进制表明方法,叫做这个数的机器数,机器数是带符号的,正数为0,负数为1。

如 :

  • 十进制数+3,机器数便是00000000000000000000000000000011
  • 十进制数-3,那机器数不便是10000000000000000000000000000011 ,想当然~ 实践是11111111111111111111111111111101,这个数是-3的补码方法,由于负数在机器中是以补码的方法存在的。

真值

真实数学意义上的数值。由于第一位是符号位,所以机器数方法值就不等于真实的数值。 如:

00000000000000000000000000000011->+3
11111111111111111111111111111101->-3

当然前面的举例是针对有符号数来说的,关于无符号数,机器数和真值是共同的。

无符号数和有符号数机器数和真值换算方法

无符号数换算:

用一个函数B2Uw(Binary to Unsigned)的缩写,长度为w来表明:

B2Uw(x⃗)=∑i=0w−1Xi2iB2U_{w}(\vec x) = \sum_{i=0}^{w-1}X_i2^i

如4位二进制数:

B2U4([0001])=0∗23+0∗22+0∗21+1∗20=0+0+0+1=1B2U_4([0001]) = 0*2^3+0*2^2+0*2^1+1*2^0 = 0+0+0+1 =1
B2U4([0011])=0∗23+0∗22+1∗21+1∗20=0+0+2+1=3B2U_4([0011]) = 0*2^3+0*2^2+1*2^1+1*2^0 = 0+0+2+1 = 3
B2U4([1001])=1∗23+0∗22+0∗21+1∗20=8+0+0+1=9B2U_4([1001]) = 1*2^3+0*2^2+0*2^1+1*2^0 = 8+0+0+1 =9
B2U4([1111])=1∗23+1∗22+1∗21+1∗20=8+4+2+1=15B2U_4([1111]) = 1*2^3+1*2^2+1*2^1+1*2^0 = 8+4+2+1 =15
有符号数换算方法

前面咱们说过有符号数在核算机中的机器数是以补码的方法存在的,其换算公式B2Tw(Binary to Two`s complement):

B2Tw(x⃗)=−xw−12w−1+∑i=0w−2Xi2iB2T_{w}(\vec x) = -x_{w-1}2^{w-1}+\sum_{i=0}^{w-2}X_i2^i

如下面4位二进制数:

B2U4([0001])=−0∗23+0∗22+0∗21+1∗20=−0+0+0+1=1B2U_4([0001]) = -0*2^3+0*2^2+0*2^1+1*2^0 = -0 +0+0+1 =1
B2U4([0011])=−0∗23+0∗22+1∗21+1∗20=−0+0+2+1=3B2U_4([0011]) = -0*2^3+0*2^2+1*2^1+1*2^0 = -0+0+2+1 =3
B2U4([1001])=−1∗23+0∗22+0∗21+1∗20=−8+0+0+1=−7B2U_4([1001]) = -1*2^3+0*2^2+0*2^1+1*2^0 = -8+0+0+1=-7
B2U4([1111])=−1∗23+1∗22+1∗21+1∗20=−8+4+2+1=−1B2U_4([1111]) = -1*2^3+1*2^2+1*2^1+1*2^0 = -8+4+2+1=-1

当然还有一种大众所知的方法:便是使用原码,反码,补码改换规则

原码,反码,补码

核算机机器数运转功率问题

首要要清楚咱们核算机中一致运用的是加法核算,对你没听错。。核算机居然不会减法,哈哈。

在补码概念提出之前,咱们来举几个比如:

计算机组成原理系列(一):浅谈计算机中的“补码”

可以看到在有负数参加的加法核算得到的结果是有误的。

如果需要得到正确的结果,核算器不得不是有其他方法去得到,这样必然就会影响运转功率。

为了处理负数在核算机中运转功率问题,科学家们提出了补码的概念。

补码:

运用补码获取真值

那怎么运用补码规则获取一个负数的真值呢?

计算机组成原理系列(一):浅谈计算机中的“补码”

假定咱们从核算中获取了一个二进制为10000001的8位机器数,怎么获取其真值。

  • step1.首要10000001是指一个补码方法机器数,实践上在核算机体系中,一切的整数都是以补码的方法存在,包括正数和负数,正数的补码便是原码自己所以一致运用补码来存储。
  • step2.依照补码到反码规则,在补码10000001基础上-1,将得到反码:10000000
  • step3.依照反码到原码规则,将契合位不变,反码取反即可得原码:11111111
  • step4.依照原码的真值概念:原码的契合位为符号位,不参加核算,其他位为真值的绝对值即可:- 127

计算机组成原理系列(一):浅谈计算机中的“补码”

补码的核算逻辑

咱们回到前面剖析运转功率时举的正正,负负,正负相加比如:

这儿咱们运用补码再来核算下:

计算机组成原理系列(一):浅谈计算机中的“补码”

可以看出,将符号以补码的方法存储在核算机中之后就可以运用加法来代替减法的操作,大大提高了核算机的运转功率。

补码的规划来历

通过文章前半部分介绍,相信你已经对补码有了一个比较全面的概念了,可是补码是怎么规划出来的呢?

数学里边有一个“补数”概念。

补数

日子中有许多比如,只要是带周期性的事务性质的都可以用补数来描述。比如:时钟或许转盘等。

计算机组成原理系列(一):浅谈计算机中的“补码”

假定当前时刻是2点,你要让时钟显示到12点,那么有两个方法。

  • 方法1.将指针顺时针拨动10个点,做的是加法:+10。
  • 方法2.将指针逆时针拨动2个点,做的是减法:-2。

关于时钟来说,不管你是方法1的加法运转仍是方法2的减法运算,指针都指向了12点,完成的作用是共同的, 那咱们就说+10和-2是两个补数,它们的绝对值之和12便是补数的模

这种规则也被应用到核算机二进制中。下面咱们运用一个比如来看:

假定要核算:(5)+(-1) = 5+(+?)

  • 5在核算机中的原码: 0 0 0 0 0 1 0 1
  • -1在核算机中的原码:1 0 0 0 0 0 0 1

要将这个减法操作变为加法操作,首要任务便是找到模,然后得到-1的正补数相加即可

来看咱们的时钟,每拨动12格为一个周期,便是说恢复了,相同的,8bit位规模是-128~127,(注意这儿咱们为了精简剖析运用的是8位来测验核算,实践核算机中场景一般都是32位格局4个字节或许64位核算)所以其一个周期便是256,也便是其模便是256(1 0000 0000),不管你是加上256仍是减少256,在二进制中,值都是不变的,由于最终一位是溢出位,不会去核算。

通过以上剖析咱们找到了-1(1 0 0 0 0 0 0 1)的模为256(1 0000 0000),-1的补数为(+255):0 1111 1111

这样就将5-1这个减法运算改变为了5+255这个加法操作

下面咱们来看5+255:

5:0000 0101

255:0 1111 1111 

二进制相加后:1 0000 0100 ->最高位溢出丢弃所以结果为4.

看到是不是和5-1结果相同呢?。

其实核算机中的补码也是这个模式:找到一个与负数等价的正补数,运用该正补数代替负数,从而将减法运算替换为两个正数加法运算,补码的出现与运算器的电路规划有关,从规划者的视点看,希望尽可能简化电路规划和核算复杂度。而运用正补数代替负数就可以消除减法器,完成简化电路的意图。

好了回过头来咱们看看开端那幅图,你看懂了么?我是小余,咱们下期见。

参考:为什么核算机中的负数要用补码表明?