在大学的学习中,一开始自认为已经学会了反码与补码,但在看到多种表述之后,反而是越来越乱,疑惑越来越多,即使记住了之后又会混淆,今天又看到了一次,为了防止以后再次忘记,写这篇博客记录一下(记录过程依据《数字电子技术(第十版)》,中英文结合) 首先从最一般的意义上,分别说一下二进制的反码和补码:
1、反码 (1’s complement)
把所有的0变为1,所有的1变为0。 如: 10110010 Binary number 01001101 1’s complement
2、补码 (2’s complement)
在反码的最低有效位上加1。 补码 = 反码 1 另一种求补码的方法:
- 从右边的最低有效位开始,往左边写下它们实际的位,直到遇到第一个1(包括1)
- 左边剩下的位求反码
如: 1011 1000 Binary number 0100 1000 2’s complement
这是在不区分正负数的情况下泛泛而谈的,其侧重点在于反码与补码如何操作,但实际上反码和补码的作用是用在带符号数上面的,下面进入重点。
3、带符号数 Signed Number
3.1 符号位 The Sign Bit
带符号的二进制的最左边的那一位就是符号位,指出这个数为正数还是负数,0表示正数,1表示负数。 下面介绍几种表示带符号数的形式。
3.2 符号数值的形式 Sign-Magnitude Form
最左边的一位是符号位,剩余的位都是数值位。其实也就是一般的带符号数的形式,数值位对于正数和负数来说都是二进制源码(in true (uncomplemented) binary)。如十进制数 25 使用符号数值形式表示成8位带符号二进制数为:
十进制数 -25 表示为:
他们之间的唯一区别就是符号位不同。
3.3 反码形式 1’s Complement Form
正数的反码形式:与符号数值形式相同; 负数的反码形式:相应正数的反码。也就是为相应正数的符号数值形式的每一位取反。
应当注意的是并不是带符号数的反码都是每一位取反。 反码和补码其实是为了解决正数和负数的加减法运算的,所以正数其实不用做什么改变,而负数改变形式后可以巧妙解决一些运算问题。比如减去某个数和加上这个数的补码是一样的,这就是为什么计算机在所有的算术运算中都使用补码来表示负整数。 理解了反码是带符号数的一种表示形式及其目的,大概就能理解为什么正数的反码是其本身,下面要说到的补码也是一样的道理。
举例:在反码表示形式中, 十进制数 25 表示为: 00011001 十进制数 -25 表示为: 11100110
3.4 补码形式 2’s Complement Form
正数的补码形式:与符号数值形式相同; 负数的补码形式:负数的反码加1。
举例:在补码表示形式中, 十进制数 25 表示为: 00011001 十进制数 -25 表示为: 11100111
3.5 总结
对于带符号数, 正数的反码和补码与原码相同; 负数的反码等于相应正数的反码,补码等于相应正数的补码。
但这样的说法是会让人产生疑惑的,因为既然正数的反码等于原码,且负数的反码等于相应正数的反码(即等于正数的原码),那正数负数的表示不就一样了。我也觉得这种说法很有歧义,但如果把第二个反码看成是一种广义上的操作,即把每一位取反,这样就没问题了,总之只要能理解就好,有时候反码就是真的“反”码,实实在在的操作。但为了避免这种困惑,倒不如表述得更清楚直接些:
对于带符号数, 正数的反码和补码与原码相同; 负数的反码等于相应正数的符号数值形式的各个位取反,补码等于反码加1。
如有不合理的地方,欢迎指正。