原码,反码,补码
原码,反码,补码
- 1、原码
顾名思义,原码就是十进制数直接转换成二进制之后添加符号位直接形成的二进制编码,其中正数的最高位(符号位)为 \(0\),负数为 \(1\)。
- 2、补码
正数的补码和原码相同,而负数的补码是其反码加一。
- 3、反码
顾名思义:正数的反码是其原码,负数的反码是其原码除符号位之外的所有位按位取反的结果。
符号位:非负数的符号位为 \(0\),负数为 \(1\)。
为何有补码
在计算机里为了简化运算,只有加法,没有减法,而使加后减少的方式只有溢出,所以要用加负数的形式溢出,实现减法。(计算时,包括符号位)。
如果 \(x\) 是一个非负整数,那么 \(-x\) 加上 \(x\) 就等于 \(0\),对于计算机,如果想实现减这一操作,仅有溢出一条路。如果 \(-x\) 为 \(x\) 取反,那么二进制下 \(x + (-x) = 111\dots11\),即全 \(1\),而 \(0\) 的二进制为 \(000\dots0\),这时如果给全 \(1\) 加 \(1\),那么就会溢出,剩余为全 \(0\),即 \(0\)。那么 \(-x\) 就应该是 \(x\) 取反加 \(1\),即: -x = ~x + 1,而这就是补码,而对于那个取反的结果我们就称为反码。
实际上是现有的反码才有的补码,反码其实也可以用,但是因为反码会导致两个 \(0\) 的 bug,后续规定死了一个 \(0\),于是才出现了补码。
如果上述不懂可以看看补数的概念:补数到底是个什么玩意儿?从根儿上理解一下 - 知乎
为什么说只能通过溢出呢?一般来说,溢出是不好的事情,比如内存溢出,水桶溢出水,刻板认为溢出是坏的,但是换一种思想来看,溢出也是一种特性,只不过这个特性有利有弊,是可以利用的,正常的加法如果没有溢出的话,就只会一直向上加,直到满了之后,溢出,回到低位,我们是为了方便才使用的溢出,而不是为了溢出而是用补码,人为可以设计减法器从而防止溢出,但是没必要,仅仅是因为没必要,可以利用溢出,所以就使用了溢出,才有了补码。不是不可以使用减法器,只不过没必要。
发展的思路?(或许)
以下没有任何依据,都是猜测,便于自己理解的。网上也找不到什么统一的答案,它们的衍生目前看来,就是计算机发展过程中,潜移默化的。早期计算机没有什么规则,是混乱的,开始信息传播也不算方便,这种用法,可能就是人传人,一点点流传下来的。至少目前我没找到什么证据,说明是谁提出的。
最开始发现了二进制,因为其性质,有人尝试把二进制引入计算机,那么需要解决的两个点就是表示和运算,运算的前提是表示,于是尝试创造适合计算机的二进制表示方式。正常思路是直接把数字的二进制按照高低电平直接给塞进计算机里面,但是这样会有符号问题,因为计算机里面只有高低电平(也就是 \(0\) 和 \(1\)),因此人们就采取了一种暴力的方法,直接取最高位为符号位,\(0\) 表示正数,\(1\) 表示负数。这样做有相当多好处,易于人的观察,而且对符号和数值进行了分离。于是尝试这个方法是否可行(这里存在 \(+0\) 和 \(-0\) 两个 \(0\),为什么还能用?因为这里只是尝试,我们不知道究竟什么样的可以使用,因此只能尝试,很多数学公式,物理定理也都是尝试出来的)。而这也就是我们说的原码。
接下来就是如何进行运算。我们想要运算尽量简单,对于基本的四则运算,乘法和除法都可以通过加减法进行,而减法可以转化为加法,因此我们只需要处理加法即可。正数加正数直接套用二进制即可,难的是正数加负数。请注意,目前是在计算机中,我们只有在数值位上的加法运算,问题就是如何利用这个加法运算实现正数和负数相加,这时候就要用到溢出了。
原码方式不适合进行溢出,于是我们需要再找一种表达方式便于溢出。我们尝试保留正数的表示方式,并规定 \(0\) 的表示为 \(00000\) 即 \(+0\) 的表示方式,看看有什么负数更好用。这个过程具体见上面 为何有补码。于是我们采用了补码进行存储数据,并惊奇的发现,这种方法使得只有一个 \(0\)(-0 = ~0 + 1,这里已经是尝试变换表达方式了,不要和最开始的原码卡死了)。
感悟
科技的发展不是一帆风顺的,中间可能会出现各种想不到的 bug,就像孟德尔超前发展,量子力学的初步提出,开始出现可能是没有道理的,造成了超前,然而超前意味着底盘不牢,容易崩塌,因此就会出现各种矛盾。好比你想到了 \(12\),然而目前知识进支持到 \(8\),你使用了 \(12\),并发现没有错误,于是一直使用,产出了 \(13,14,15\),但是中间的 \(9,10,11\) 就空下了,这时候人们都认同 \(12\),但是没有由来的 \(9,10,11\)。因此就会出现危机,就会出现停滞。很多大的发展都是这样的,在一种似对非对的定理中前进,然后发现错误,修正再前进。这种没有道理,就是创新吧,或者说是一瞬的 idea。
很多东西就是很神奇,有时候,想得到这个 \(9\),就需要有这个 \(12\) 这个引导才可以。科学很多停滞的时候,就是在反复横跳在这个 \(9\) 和 \(12\) 中一点点完成 \(9,10,11\)。 一个著名的例子——微积分。
补码的存储顺序
因为补码的存储方式比较特别,其存储的数据和真实值之间的关系是这样的(下面以 \(8\) 位为演示):
-1 -2 -3 ... -127 -128 | 127 126 ...2 1 0
11111111 11111110 11111101 ... 10000001 10000000 | 01111111 01111110 ... 00000010 00000001 0000000
其中 -128 是比较特殊的一个数(在 \(8\) 位下),因为它没有对应的原码和补码,因为这本身是原本的 \(-0\),但是 \(0\) 已经被统一成 \(00000000\) 了,所以为了不浪费,就有了这个特殊的一个数。
一个标准的教科书结论是:在 n 位 原码/反码表示法中,绝对值大于 \(( 2^{n-1} - 1 )\) 的数(即 \(-2^{n-1}\))没有原码和反码,只有补码能表示。

浙公网安备 33010602011771号