本篇文章主要学习记录原码、反码以及补码的相关知识。
原码
计算机为了表示负数,在二进制数值前面增加一位符号位(即最高位为符号位):正数该位为0,负数该位为1,其余位表示数值的大小。
比如,10的二进制原码表示为0 1010
,-10的二进制原码表示为1 1010
。
这种编码方式被称之为原码,原码的优点比较明显,就是简单直观,容易被人理解。
存在的问题
当正数+正数时,比如5+2,即0 0101 + 0 0010 = 0 0111
,原码0 0111
表示十进制中的7,即5+2=7。此时没有任何问题。
当正数+负数时,比如5+(-2),即0 0101 + 1 0010 = 1 0111
,原码1 0111
表示十进制中的-7,即5+(-2)=-7,显然是不正确的。
原码这种编码方式仅支持正数+正数(即加法操作),而对于正数+负数(即减法操作)这种情况,显然不支持。
反码
反码是基于原码计算得来,表示方式是:正数的反码是其本身。负数的反码是在其原码的基础上,符号位不变,其余各个位取反。
举例说明,10的二进制反码表示为0 1010
,-10的二进制反码表示为1 0101
。
反码计算的规则:
- 反码运算时,其符号位与数值一起参加运算。
- 反码的符号位相加后,如果有进位出现,则要把它送回最低位去相加(循环进位)。
- 用反码运算,其运算结果亦为反码。在转换为真值时,若符号位为0,数位不变;若符号位为1,应将结果各个位取反才是其真值。
比如5+(-2),反码表示为0 0101 + 1 1101 = 0 0011
,即5+(-2)=3。
再看一个(-5)+2,反码表示为1 1010 + 0 0010 = 1 1100
,反码1 1100
对应原码1 0011
,其结果为-3。
存在的问题
当5+(-5)时,即0 0101 + 1 1010 = 1 1111
,反码1 1111
对应原码1 0000
,其真值为-0。尽管+0和-0是一样的,但是0带符号是没有意义的。
反码虽然解决了减法的问题,但是却没有解决0的符号问题。
补码
补码是在原码和反码的基础上衍生出来的,补码的表示方法是:正数的补码就是其本身。负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1(即在反码的基础上+1)。
补码计算的规则:
- 补码运算时,其符号位与数值一起参加运算。
- 补码的符号位相加后,如果有进位出现,则进位被舍弃。
- 用补码运算,其运算结果亦为补码。在转换成原码时,如果是正数,其补码就是原码;如果是负数,该补码的补码就是其原码。
先来看一下5+(-5),即0 0101 + 1 1011 = 0 0000
。补码0 0000
对应十进制为0。没有问题。
再来看一下5+(-6),即0 0101 + 1 1010 = 1 1111
。补码1 1111
对应原码1 0001
,即5+(-6)=-1。也没有问题。
有了补码,0的表达方式就唯一了,如果是8位的话,那么就是固定的0000 0000
。同时,补码的取值范围也从原码和反码的[-127, 127]
(即[11111111, 01111111]
变成了[-128, 127]
,其中补码1000 0000
来表示-128。
总结
正数的反码是其本身,负数的反码是在原码的基础上,除符号位外,其余位取反。
正数的补码是其本身,负数的补码是在原码的基础上,除符号位外,其余位取反,然后+1(即在反码的基础上+1)。
负数的补码的补码是其原码。
参考文章: