最近在搞项目,被团队协作搞的头都大了,都是泪啊,本来我们组的人技术水平都不错,如果每个人单独写这个项目的话大概3天就能搞定,结果最后因为各种问题写了3天勉强把后台写完,写的我都怀疑人生了,今天实在顶不住了,就写写博客释放一下压力吧,好了,回归正题
原码很好理解,就是最初始的编码,我这里用Java中的byte来解释
byte b=1;
b等价于0000 0001
b+1等价于0000 0001+0000 0001=0000 0010
这里的0000 0001便是原码,看起来直接用原码来计算也没什么问题,但问题其实是存在的,如果我们用原码来进行运算,类似于下面的计算式,问题就来了
byte b=16;
b-1等价于0001 0000-0000 0001=0000 1111
相比加分而言,用原码来计算减法显然极其浪费性能,原因很简单,我们知道,计算机之所以只有两种状态01是因为电路只有开和关两种状态,加法只需要考虑是否需要进位即可,但是对于减法而言如果遇上上述这种情况,如何才能减去数字呢?首先要考虑当前位是否满足减数的需求,不满足的话需要向前考虑,向前考虑是否满足的同时还要考虑当前位的值,也就是说,对于减法来说,原码需要操作多个位上的数才能得到正确结果,例如,下面这个例子,为了方便阅读,我直接用原码表示,并忽略符号位
1010-1001
首先,要注意的是,对于这种底层运算来说,每个位上的01都是相互独立的,如果你们玩过位运算就知道,我们可以单独操作其中的某一位数,但是无法得到这位数上的值的意义,因为对于计算机来说,每一位数都是相同的,除了01并没有其他意义,之所以可以用来表示像2,3这样的非01数,是因为人类对其赋予了意义,所以如果用每一位数独立的眼光来看,10肯定不能满足减去1001的需求,但是单独的1000也不能满足减去1001的需求,所以我们至少需要位运算3次
1010=》0010
0010=》0000
0000=》0001
但是这是我们已经提前知道答案的情况下,如果让计算机自己进行,至少需要以下几步,判断第一位的情况=》均为1,进行位运算得到第一位为0=》判断第二位,均为0,下一位=》被减数为1,减数为0,将1存放至另一个值中=》放入0,取出10,进行位运算=》00=》01=》将01赋值给原数后两位
如果最终减数大于被减数,还需要符号位变为1,然后进行剩余数的加法操作,显然,对于计算机来说,减法的效率是极其低效的,于是,人们想出了反码,既然减法效率低,那把减法转换为加法不就行了吗?小学数学老师就告诉过我们,1-1=1+(-1),事实上,这也是可行的,那么怎么表示-1呢?最简单的方法,将一个正数连同符号位取反,就是这个数的负数,也就是反码,让我们试试
1+(-1)=0
0000 0001+1111 1110=0000 0000
1+(-2)=-1
0000 0001+1111 1101=1111 11110=-1
但是其实这里还有一个问题,对于反码0000 0000和1000 0000来说,他们都表示0,而-0显然没有任何意义,所以人们又想出来补码这个东西,规定负数的补码除了是对应正数的取反之外,还要加一,以屏蔽-0这样的数,这样一来,对于1000 0000这个值,就可以用来表示-128,不会空出一位无效的-0