一、原码
原码定义
原码(true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小.
比如我们用8位二进制表示一个数(以下例子均默认为八位二进制)
数 | 原码 |
---|---|
127 | 01111111 |
+0 | 00000000 |
-0 | 10000000 |
-127 | 11111111 |
由上表可知8位二进制的原码表达的范围是 -127-----127
原码的优点
简单直观,便于输入输出
原码的缺点
当有负数参与加减运算时,计算会变得复杂最直观的如 00000001(1)+10000001(-1)=10000010(-2)显然不正确。所以符号位需要和数值位分开运算,这样明显增大了硬件的消耗。
为此引入了另一种数的表示方式 补码。
反码
反码是原码求补码的格过度。(个人理解)
原码求反码
正数的反码是其本身
负数的反码将其原码除符号位外的所有位取反(0变1,1变0)
例-9的原码是00001001,反码是11110110
补码
反码求补码
正数的补码与原码,反码相同 。
例:+9的原码,反码,补码都是00001001。
负数的补码:将与之对应的反码加1 。
例:-9的原码是10001001,反码是11110110,补码是11110111
数 | 原码 | 反码 | 补码 |
---|---|---|---|
127 | 01111111 | 01111111 | 01111111 |
1 | 00000001 | 00000001 | 00000001 |
+0 | 00000000 | 00000000 | 00000000 |
-0 | 10000000 | 1111 1111 | 00000000 |
-1 | 10000001 | 11111110 | 11111111 |
-127 | 1111111 | 10000000 | 10000001 |
-128 | 无 | 无 | 10000000 |
从上表中可以发现,0的补码是唯一的,而且补码可以多表示一个数(-128),这也就是计算机中一字节(8比特)为什么可以表示-128——127的理由了。
补码的运算规则
通过将原码转为补码,可以发现补码间能直接相加或相减
补码的加法规则是:[X + Y]补 = [X]补 + [Y]补
补码的减法规则是:[X - Y]补 = [X]补 + [-Y]补
对于加后有溢出的情况,舍去最高位即可
例: 如-1加-127得到的是110000000,是九位二进制,舍去最开始的1,得到的即是-128的补码。
为什么补码能解决负数加减法问题,以及负数求补码的另一种思路
原码之所以不方便加减法是因为当有负数参与运算时,符号位不统一导致结果不正确的问题。其实简而言之,就是一对相反数相加不为0,如在原码中(-1)+(1)的结果为(-2)
而已知在原码中正数之间是满之间足加减法的直接运算,因此只需要保留正数的表达方式,改变负数的表示方式,就能让正负数都满足加减法运算。说白了,就是让(1)+(-1)=0。当然首先我们要规定0的表示方式只能是00000000,不然负数的表示方式就会不唯一。咱们将这种数的二进制表达方式称为补码。
已知(1)的补码保留了原码的表达方式是00000001,可以很简单得推出(-1)的补码是11111111(即0-1)。且(2)得补码是00000010,可推出(-2)的补码是111111110。以此类推。由此种方式得出的补码自然而然可以解决正负数之间的加减问题。
因此我们不难推出负数补码的另一种计算方式。即九位二进制的0(000000000)减去该负数的相反数的原码。