众所周知的:正数的的反码和补码都是其原码本身;
负数的反码是(除符号位外)各位取反;
负数的补码是(除符号位外)各位取反后加1,操作起来也就是“从原码的最后一位开始向前,直到第一个1(包含这个1)的位都不变,把第一个1和符号位(不包含符号位)之间的所有位取反”,道理一样。
运算如下所示,补码可以用加作减,正确实现:
0000 0010 +2(原码表示法)
0000 0010 +2(补码表示法)
0000 0100 +4(原码表示法)
0000 0100 +4(补码表示法)
0000 0011 +3(原码表示法)
0000 0011 +3(补码表示法)
1000 0011 -3(原码表示法)
1111 1101 -3(补码表示法)
0000 0001 +1(原码表示法)
0000 0001 +1(补码表示法)
1000 0001 -1(原码表示法)
1111 1111 -1(补码表示法)
下面是补码的运算:
2-3=-1
1111 1111 -1(补码表示法)
4-3=1
0000 0001 +1(补码表示法)
3-3=0
0000 0000 0(补码表示法)
——注:0的原码有两种,0的补码就一种
补码的由来:
原码运算:
0000 0010 +2(原码表示法)
1000 0011 -3(原码表示法)
2-3=-1
1000 0101 -5(原码表示法) ——错误!
——显然,采用原码运算只可以正确实现两个正数相加(当然如果存在减法器的话就另当别论了)
反码运算:
0000 0010 +2(反码表示法)
1111 1100 -3(反码表示法)
2-3=-1
1111 1110 -1(反码表示法) ——正确!
;
0000 0011 +3(反码表示法)
1111 1100 -3(反码表示法)
3-3=0
1111 1111 -0(反码表示法) ——有问题!因为还有+0(反码
0000
0000)
——显然,采用反码运算唯独不能正确实现等数相减
补码运算:
0000 0010 +2(补码表示法)
1111 1101 -3(补码表示法)
2-3=-1
1111 1111 -1(补码表示法) ——正确!
;
0000 0011 +3(补码表示法)
1111 1101 -3(补码表示法)
3-3=0
0000 0000 0(补码表示法) ——正确!
——显然,采用补码运算可以正确实现全部运算
最后:
以8位为字长时:
原码表示数范围:(-127~-0
+0~+127)
反码表示数范围:(-127~-0
+0~+127)
补码表示数范围:(-128~0~+127)
原码和反码表示数范围一样,补码只是把前两者中的“-0”用“-128”替换了;同时也就是说,8位字长时,没有“-128”的原码和补码。
——而我们所用的高级语言(C、汇编等)用的都是原码,而在计算机底层中所用的是补码。