补码是啥,它跟原码反码有啥关系?
相信大家都听过原码、反码、补码,需要知道的是,这三种都是有符号位的表示方法,第一位是符号位,1为负,0为正。如果是无符号,就不用分那么多了,直接转成二进制就是了,毕竟不用考虑负数。
总结:正数几乎只有一种码,不论用什么码去表示,它都是一样的。而反码补码更像是为负数“服务”的,他们的表示方式都有所不同。
到这里为止,这是大部分人都知道的,我在课本上学的也是如此,它教了我怎么计算一个有符号数的原码反码补码,我却没有去弄清楚它们存在的意义。在这篇笔记,我会把我理解的写出来,为什么计算机中,有符号数都是用补码表示的。
为什么计算机用补码表示负数?
补码的本质
在回答2的补码为什么能正确实现加法运算之前,我们先看看它的本质,也就是那两个步骤的转换方法是怎么来的。
要将正数转成对应的负数,其实只要用0减去这个数就可以了。比如,-8其实就是0-8。
已知8的二进制是0000 1000,-8就可以用0-8:0000 0000减去0000 1000得出
00000000
-00001000
---------
这时我们会发现不够减,我们都知道当位不够减的时候,会“借位”,这时就相当于是1 0000 0000减0000 1000了
100000000
-00001000
---------
11111000
而1 0000 0000等价于1111 1111+1,现在可以拆分成两个式子
11111111
-00001000
---------
11110111
+00000001
---------
11111000
这就是补码的转换步骤
由0减去8得出了-8,也就是补码(-8)和原码(+8)相加的和为0
这里有个前置条件,就是我们限定了只有8位,所以借位了就不用考虑“还”的问题了,如果是16位,则是继续往前借,直到最高位以后,也同样不必考虑还的问题,多少位的区别只是前面会多几个“1”。
为什么正数加法适用于2的补码?
现在测试一下,用补码是否能解决上面的问题,只用加法就计算出正确答案。
实际上,我们要证明的是,X-Y或X+(-Y)可以用X加上Y的2的补码完成。
Y的2的补码等于(-Y)+1。所以,X加上Y的2的补码,就等于:
X + (-Y) + 1
我们假定这个算式的结果等于Z,即 Z = X + (-Y) + 1
接下来,分成两种情况讨论。
第一种情况,如果X小于Y,那么Z是一个负数。这时,我们就对Z采用2的补码的逆运算,求出它对应的正数绝对值,再在前面加上负号就行了。所以,
Z = -[-(Z-1)] = -[-(X + (-Y) + 1-1)] = X – Y
第二种情况,如果X大于Y,这意味着Z肯定大于,但是我们规定了这是8位机,最高的第9位是溢出位,必须被舍去,这相当于减去。所以,
Z = Z – = X + (-Y) + 1 – = X – Y
这就证明了,在正常的加法规则下,可以利用2的补码得到正数与负数相加的正确结果。换言之,计算机只要部署加法电路和补码电路,就可以完成所有整数的加法。
*深入解析
首先,为什么补码可以用加法得到相减的结果?
之所以可以这样做,是因为计算机的有符号数是有位数“上限”的,8位计算机就是8位的上限,16位的就是16位的上限,一旦超出这个上限,多余的位就会被丢失,相当于不存在了
举例来说,假设现在我们是4位的计算机,它的表示范围是-8~7
我们现在尝试输出结果超出4位的运算:
1111+0001
先不去想他们值是什么,我们现在知道它的结果应该是1 0000,但由于我们现在是4位的机器,所以超出的一位自然就被“丢弃”了,所以结果应该是0000
现在再去看它们的值,是 -1+1=0,结果是准确的,我们用加法成功的做出了减法的效果,而这都是因为我们把超出最高位的位数“丢弃”了,这就是为什么补码可以用加法得到减法的效果。
那十进制呢,十进制可以这样吗?
我们在十进制运算的时候,几乎没有位数限制,毕竟人不是机器。当没有位数限制的时候,你无论怎么加,都无法作出丢弃超出最高位的位数的行为,因为根本没有最高位,所以是无法用加法作出减法的效果的。
如果一定想用十进制作出如上的效果需要两个条件,限制位数和重定义数字的值。
由于限制的位数,同时产生了一个衍生的条件,就是在有效位里,我们可以表示的数字是有限的,不像我们现实中的运算,正负无限延伸。既然产生了这个条件,我们就必须考虑在这个范围内,每个符号的顺序。
0 1 2 3 4 5 6 7 8 9 ( 0 1 2 3 4 -5 -4 -3 -2 -1 )
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/208119.html原文链接:https://javaforall.net
