原码、反码、补码

原码

原码(true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。
例如,我们用8位二进制表示一个数,+11的原码为00001011,-11的原码就是10001011
一个 byte 有 8bit,最大值是 0 1 1 1 1 1 1 1 (+127),最小值是 1 1 1 1 1 1 1 1 (-127)

反码

正数的反码是其本身(等于原码),负数的反码是符号位保持不变,其余位取反。 反码的存在是为了正确计算负数,因为原码不能用于计算负数.

计算负数

1
2
3
4
5
6
7
8
9
-8 - 1 = -9
10001000
转为反码
11110111
-00000001
——————————
11110110
转为反码
10001001 刚好就是-9

也就是说整个计算过程为 ((-8)反码 - (1)原码)反码

跨零计算
负数跨零进行计算的话,计算结果不对

1
2
3
4
5
6
7
8
9
10
-8 + 9 = 1
10001000
转为反码
11110111
+00001001
100000000
去掉超过8位的位
00000000
转为反码
11111111

可以看到明显不对,这个时候就需要补码了

补码

正数的补码是其本身,负数的补码等于其反码 +1

跨零计算

1
2
3
4
5
6
7
8
9
10
-8 + 9 = 1
10001000
转为反码
11110111
转为补码
11111000
+00001001
100000001
去掉超过8位的位
00000001

可以看到此时的值就是对的
总结下此时的计算过程 (-8)补 + (9)原

模的概念

看了上面的一些概念,肯定有人会疑问,为什么负数的补码是反码加1,其实理解了模的概念,这些反码和补码就很清楚了。

摘录自补码的百度百科

“模”是指一个计量系统的计数范围,如过去计量粮食用的斗、时钟等。计算机也可以看成一个计量机器,因为计算机的字长是定长的,即存储和处理的位数是有限的,因此它也有一个计量范围,即都存在一个“模”。如:时钟的计量范围是0~11,模=12。表示n位的计算机计量范围是,模=.“模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算。
就是取反后加1。
假设当前时针指向8点,而准确时间是6点,调整时间可有以下两种拨法:一种是倒拨2小时,即8-2=6;另一种是顺拨10小时,8+10=12+6=6,即8-2=8+10=8+12-2(mod 12).在12为模的系统里,加10和减2效果是一样的,因此凡是减2运算,都可以用加10来代替。若用一般公式可表示为:a-b=a-b+mod=a+mod-b。对“模”而言,2和10互为补数。实际上,以12为模的系统中,11和1,8和4,9和3,7和5,6和6都有这个特性,共同的特点是两者相加等于模。对于计算机,其概念和方法完全一样。n位计算机,设n=8,所能表示的最大数是11111111,若再加1成100000000(9位),但因只有8位,最高位1自然丢失(相当于丢失一个模)。又回到了 00000000,所以8位二进制系统的模为2的8次方。在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以了。把补数用到计算机对数的处理上,就是补码。

回到上面 -8 + 9 = 1这个例子,用模的来理解(8位2进制数的模为128)就可以转换为 9 - 8 = 9 + 120 = 129
129 转为2进制表示即为 100000001,因为最多显示128,只有8位,所以最高的第9位去掉,即为00000001 = 1。