关于原码、反码、补码

关于原码:

原码表示法是机器数的一种简单的表示法,其符号位用0表示正号,用1表示负号,数值一般用二进制形式表示。

关于反码:

机器数的反码可由原码得到,如果机器数是正数,则该机器数的反码与原码一样;如果机器数是负数,则该机器数的反码是对它的原码(符号位除外)各位取反而得到的。

关于补码:

1、计算机里面,只有加法器,没有减法器,所有的减法运算,都必须用加法进行,而直接使用原码的加法规则不能适应全部运算

比如对于一个计算式:

如果直接用原码相加:

可以看到,如果按照正常的加法规则,就会得到的结果,转成十进制就是。显然,这是错误的答案。也就是说,在这种情况下,原码的加法规则不适用于正数与负数的加法,而且对于负数加负数,直接使用原码计算也会出错。

再看看用补码相加:

可以看到,按照正常的加法规则,得到的结果是。注意,这是一个位的二进制数。我们已经假定这是一台8位机,因此最高的第位是一个溢出位,会被自动舍去。所以结果就变成了(这里得到的是补码),转成十进制正好是8。这说明了,补码表示法可以将加法运算规则扩展到整个整数集,从而用一套规则就可以实现全部整数的加法。

2、正数的补码不变,负数的补码用模减去绝对值

模是指一个计量系统的计数范围。如时钟等。计算机也可以看成一个计量机器,它也有一个计量范围,即都存在一个“模”。例如:
时钟的计量范围是,模 。表示n位的计算机计量范围是,模

假设当前时间为3点,而时钟上显示的时间为5点,那么调整到正确时间可以往后前调2小时,也可以往后调10小时,这样-2和+10对时钟而言其作用是一致的。在数学上称12为模,写作 mod 12 ,而称-2是+10以12为模的补数,或-2和+10关于模12同余,记作:

进一步分析发现, 往后调3小时、15小时、27小时…对时钟而言其作用是一样的, 即:

对于正数,其补数等于这个数加上模,再对模求余,即正数相对于模的补数就是正数本身;

对于负数,在时钟上,表示逆时针旋转将分针旋转 圈,但由于时钟本身是顺时针旋转的,且顺时针旋转圈,也能指向和逆时针旋转圈一样的位置,所以负数可以用其正补数来代替,即运算中都是加法),即:

由此可见:

  • 1、一个负数可以用它的正补数来代替,而这个正补数可以用模加上负数本身(或模减去其绝对值)求得;

  • 2、一个正数和一个负数互为补数时,它们的绝对值之和即为模数;

  • 3、正数的补数还是该正数本身。

将补数的概念,引申到计算机中,就出现了补码这种机器码。因此,正数的补码不变,负数的补码用模减去其绝对值

3、原码、反码、补码对比

8位原码和反码能够表示数的范围是 ,8位补码能够表示数的范围是

对于机器数-8在8位系统(mod )中:

  • 其原码为:

  • 其反码为:

  • 其补码为:

  • 其补数为:模

这里的原码和反码的第八位是符号位,其表示范围为

而补码实际上是没有符号位的,将负数用补码表示,实际上是实现了一种从的映射。如下所示:

补数 机器数 补码
255 -1 1111,1111
254 -2 1111,1110
253 -3 1111,1101
252 -4 1111,1100
251 -5 1111,1011
248 -8 1111,1000
246 -10 1111,0110
236 -20 1110,1100
226 -30 1110,0010
216 -40 1101,1000
206 -50 1100,1110
196 -60 1100,0100
186 -70 1011,1010
156 -100 1001,1100
129 -127 1000,0001
128 -128 1000,0000
127 127 0111,1111
100 100 0110,0100
70 70 0100,0110
60 60 0011,1100
50 50 0011,0010
40 40 0010,1000
30 30 0001,1110
20 20 0001,0100
10 10 0000,1010
5 5 0000,0101
4 4 0000,0100
3 3 0000,0011
2 2 0000,0010
1 1 0000,0001
0 0 0000,0000

4、关于-128的补码

-128是一个负数,所以它的补码是它的“模”减去它的绝对值,即:

对于-128,它只有反补码,没有原码和反码。

5、为什么负数的补码等于源码的反码加一

可以这样推导:

1
2
3
4
1,0000,0000 - 0xxx,xxxx //对于负数1xxx,xxxx 其绝对值为0xxx,xxxx 模减去绝对值,即补码
= (1111,1111 + 0000,0001) - 0xxx,xxxx
= 1111,1111 - 1xxx,xxxx + 0000,0001
= 1yyy,yyyy + 0000,0001 //反码加一