原码,反码,补码这三种看似是三种编码方式,其实可认为是计算机为解决减法问题的一条解决路径(版本迭代)。注意:这三种编码方式只是一种表示方式并不能解决溢出问题,也就是说计算不当,该溢出还是要溢出。以下讨论的情况均为在不溢出的情况才能正常运行。
这几种码的讨论背景是什么?
数的减法可以被分为这几种情况:正数加负数,负数加负数,正数加正数,后面两种都有可能溢出,因此不在讨论范围内,只有正数加负数不管怎么算都不会溢出,因此可有作为讨论背景。
原码最好理解就是所有正整数的二进制表示。补码比较难理解了,为什么是原码取反加1就变成了补码?
接下来我就以4位二进制为例解释为什么是取反加一。
经过计算我们可以发现对于1-8中任意一个数A有(16-A) = -A的补码 = A取反加一。只是计算上恰好相等吗?不是,这是因为在计算结果没有溢出(-8到7)的情况下0和16其实是一回事。
解释了第一个问题,解释第二个问题为什么要引入补码?
原因很简单:为了利用加法来解决减法运算。换句话说就是0-15一共16个数,正数为0-7的时候怎么表示-8到-1的问题。用群论的话说可否定义一种规则使得-8到7中的运算形成一个群。反码之所以不行,是因为它没办法形成一个群(单位元不唯一,有+0和-0)。
第三个问题那这个补码该如何定义呢?
如果把运算看作一个动作的话,顺时针为+,逆时针为-,-1就是原码0逆时针转一格,+1就是原码0顺时针转一格。
比如2-1,实际上是2+(-1),这很好理解,难理解的是这个-1该怎么表示?
其实很简单0-1不就是-1,于是-1可以用+15的源码来表示,-2也一样。
但是经过计算人们发现
对于2-1
0010+1111=10001,不成立,但如果减掉16结果正好是1。
对于1-2
0001+1110=01111,不考虑01111中的0时恰好成立。
然后补码就被提出了。同时高位被舍弃的1和0在多精度整型减法运算中刚好可以被用到。