文章标题

计算机为什么采用补码存储数值

初学C,问题源自:为什么C中的int类型(16位)的下溢下限为-32768而上溢上限却是32767。
首先说吧,32767很容易理解,32767=2^15-1 (因为要有一个符号位),但为什么下溢的时候分明是15位来表示的数会出现32768呢?

首先从原码重点内容讲起,原码即为计算机中对数值的二进制表示,如 5用二进制表示为0000 0101 ;

其次就是反码,反码,顾名思义取反,对于正数来说,反码与原码相同;对于负数来说,反码为原码的各位取反(符号位除外),如(0011 0111)反= 0011 0111 (1101 0010)反= 1010 1101 ;

再次就是补码,计算机中,数值疑虑用补码表示和存储的,正数的补码与原码相同,负数的补码为其反码+1,如(0101 1101)补=0101 1101 (1101 0010)补=1010 1110

由于计算中的CPU只有加法器,没有减法器,所以在计算机采用原码做减法是会存在这样的问题:对于1-1=0
看做1+(-1)=0 二进制表示 0001+1001=1001 变成了十进制的负1而不是0。补码的出现很好的解决了这个问题,由于采用补码运算,则补码加法成为:[X+Y]补 = [X]补 + [Y]补同时,补码的减法变为:[X-Y]补 = [X]补 – [Y]补 = [X]补 + [-Y]补 补码的乘法变为:【X*Y】补=【X】补×【Y】补;在此我们以减法为例说明补码的优势,还以上述为题为例:(0001)补+(1001)补 = 0001 + 1111 = 0000 (最高位的进位省略),这样就顺利得到了0

另外,补码还解决了原码中存在两个0 的问题(即+0 和 -0),以8进制为例,int_8的取值范围应该是-127~ -0和+0~ 127 即存在正0 0000 0000 和 负 0 1000 0000 ,但是在两个0转换为补码后全部都变成了0000 0000,细心的你会说原来8位编码表示的256的二进制数在补码中不就少了一个吗?
对,当然是少了一个,对于1000 0000 ,任何原码都不能转换成补码后成为1000 0000的形式
但数是死的,人是活的,不能让XX憋死不是? 所以人为规定补码中 1000 0000 表示 -128 ,这就很好的解释了,为什么8位的整形变量的下溢下界会是-128而上溢上届是127了。

同样,对于16进制int,也是这样, 表示范围成了 – 32768 ~ 32767 (32768=2^15)

点赞