怎样直白地理解补码原理?
问这个问题的人多了解补码的一些知识,最常用的补码等于原码加一,但是不怎么理解补码到底是怎么工作的。 下面是几个常见的问题,理解了它们,也就理解了原理。
什么是补码? —— 一种表示数字的编码(废话)
关键是为什么要有它? ——因为计算机底层只能处理加法,所以正数加负数就是一个正数减正数,我们想把它转换成正数加正数,所以补码就被发明了,补码用来将 正数不管,负数变成正数,这样就满足了要求。
"补"字什么意思呢? ——来源于互补的概念,说到互补得说同余,两个数mod M 余数相同就说他们模M同余,如果这两个数绝对值相加为M,就说他们互补(-4和8模12同余,4+8=12所以-4 和8互补)。 M在我们进行运算时就相当于给 定长 的数 的大小,比如8位定长,则M就是256(为什么,看下面)
为什么要有M? ——举钟表这个最常被举的例子,钟表的M是12因为格数不能超过12,4+8=12,所以再钟表上顺时针走4格和逆时针走8格是不是一样的,
我们的8位定长256也是同样的道理,把0->255(8位能表示的数个数)填在圈中,这样 -1与255互补,-2与254互补,-127与129互补 (相加都为256,互补,当然也同余), 前面我们说只取负数的补码,正数不管,所以我们令-1的补码是255.....-127的补码是129(负数的补码为M-|这个数|,正数不变), 神奇的事情发生了,负数的补码最高位正好在二进制中为1,而正数不是,于是正数的补码和负数的补码就这样隔开了,
剩一个数给谁? ——为了公平表示正负数,我们把256个数分给-127->127,但是还有一个呢
|-128|+128=256,我们到底要哪个呢,对了,因为负数要有1这个符号位做区分,所以256就用来表示-128了,这也大概是为什么八位正负值表示-128->127的原因吧(注意-128在原码中是没有定义的,因为原码中10000000,1就是符号位,没有补码的含义,他和00000000都是0)。
那为什么正负数要隔开呢? ———为了制造出类似原码的符号位,这样补码转换原码的时候,就可以区分转换了。正数不变,负数取反加一。
为什么是取反加一呢? ———根据原码负数时 [x]补=M-|x|推出来的 ,这是原始式子,也挺好记的比如-8的补码就是256-8 = 248,-128的就是128,。
那为什么原码取反加一为补码,补码取反加一为原码? ———因为负数的补码,根据前面所说和原码是互补的,根据[x]补=M-|x|推出来的公式。肯定是相同的,所以求原码也就相当求补了。