学习计算机语言对于补码的计算是避免不了的,有时候写的程序出现意向不到的结果,其实都是补码在搞鬼( ̄┰ ̄*)。今天有幸把我所对补码的理解做一点总结,但愿对看到此博文的博友有所帮助。

在这里就不对补码的定义做过多的强调了,不懂的问度娘。

补码计算方法一:

正数的补码是它本身比较简单,在这里介绍一下负数的补码。

首先用语言来描述一下:负数的补码 =补码取绝对值转换成二进制然后取反再加1得到的。

如-6(二进制形式:1110b[不是BCD码只是单纯的二进制运算得到的]),

|-6|=6=0110b;对0110取反=1001;对1001加1=1010;此时-6的补码就是1010.还是来个直观的看看吧。

wKioL1gu1p-yUGJXAAAXEE4mrxw330.png

这种方法通常是我们刚接触补码时,常用的计算方法。如果位数少的话还可以接受,如果位数多的话,你懂的。。。。。。。

补码计算方法二:


一般对于基数为B的而言的补码,是指从(B-1)中减去赋予数值的各位数字,在最低为上加1得到的。(纳尼,是不是有点懵啊。。。嘻嘻接着往下看)

如说我们长用的十进制它的基数B就是10,而所谓的从(B-1)[在这就是9啦]中减去各个数字的意思就是,用9减去各个数值位,然后再加1.举例如下:

7556的10进制补码=9999-7556+1=10000-7556=2444.

补码通过加法表现减法:8945-7556=1398;等价于8954+(7556的10进制补码)=8954+2444=11398,如果忽略溢出的最高位,可得结果为1398.

我们也可以用计算二进制的补码:还是以-6为例

第一步:对要进行计算补码的数值取绝对值|-6|=6;

第二步:取绝对值后的值进行二进制转换6=0110b;

第三步:用基数-1去减去各个位的数值(二进制基数为2,B-1=1)1111b-0110b=1001b;

第四部:第三部计算的数值进行加1=1001b+1=1010b;

得到-6的补码与第一种计算的方法相同。

同样我们把-6转换成8位有符号的16进制(最高位为1)=0x86(1000 0110b)

用第二种方法计算-6的补码=0XFF-0X86+1=0X7A=01111010b,可以看到后四位和上面计算的相同。


总结:

  1. 对于十进制数计算成二进制数的补码,需要对十进制数进行取绝对值,让后再转换成二进制,用方法一或方法二都可以计算出补码。

  2. 对于16进制的补码同样可以转成二进制后,通过方法一或方法二进行计算,

  3. 其实对于(n位的)二进制或16进制的补码=1的后面n个0-n位的二进制或十六进制

    如0x86的补码=0x100-0x86=0x7A;

    如0110b的补码=10000b-0110b=1010b;



在程序中如果写成:

int i=0x80000001;      //其实是-2147483647的补码

printf("%d\n", i);    //其结果为-2147483647,而不是-1,所以这里值得我们注意。

我们在这里利用方法二可以计算出0x80000001的源码的绝对值=0x100000000-0x80000001=0x7FFFFFFF=2147483647,加一个负号就是源码了-2147483647。

(我们只对负数进行补码的计算)