原码、补码

计算机的整型数可以分为有符号数和无符号数。有符号数使用最高位作为符号位。以一个字节(8bits)的存储为例。无符号为表示区间为[0, 255], 有符号数为[-128, 127]。
计算机二进制表示中,整数常用补码表示。正整数时补码和原码是等价的。

原码表示法

使用最高位作为符号位,其余位按照正常的换算方式。例如+1,-1分别表示为0000 0001,1000 0001。两者只有符号为不同。原码表示的区间为[-127, +127]。

补码表示法

正数的补码等于原码,负数的补码等于对应正数的取反加一。
举例来说,+127的补码为0111 1111,-127的补码是1000 0001。
这让负数补码看起来很反直觉。给定一个负数补码,我想知道对应的值,得减一取反得到绝对值再加上负号。这有的加一,有的减一的完全反应不过来。
其实有一种符合直觉的看法,先定义正数补码然后根据正数定义负数补码。基于
x + ( − x ) = 0 x+(-x)=0 x+(x)=0
x x x为正数, − x -x x就是负数,上式表示为正数加上负数。假设我们已经定义好了正数补码,比如+127(0111 1111)。我们将负数补码表示定义为与对应正数补码表示相加等于零的数。因此负数应该表示为(1000 0001),这就是-127。
1000 0001的计算步骤分为两步,

  • 第一找到一个数与对应正数相加使二进制变成全1。
    0111 1111 + 1000 0000 = 1111 1111 0111\quad1111 + 1000\quad0000=1111\quad1111 01111111+10000000=11111111
    这是得到1000 0000。
  • 接着再让1111 1111溢出,变成真正的零值。
    0111 1111 + 1000 0000 + 0000 0001 = 1111 1111 + 0000 0001 = 1 0000 0000 0111\quad1111 + 1000\quad0000 + 0000\quad0001 \\ = 1111\quad1111 + 0000\quad0001 \\ =1\quad0000\quad0000 01111111+10000000+00000001=11111111+00000001=100000000
    把溢出位置扔掉就是最终的结果。
    上面是从正数算负数,那么从负数算正数也可以使用同样的办法,压根不用考虑到底是加一还是减一。
    举个例子:
    -127(1000 0001) -> 0111 1110+0000 0001->0111 1111(+127)
    +127(0111 1111)-> 1000 0000 + 0000 0001 -> 1000 0001(-127)
    所以不管从正数推负数还是负数推正数都只用加一操作。

用正负相加等于零的方式还带来一个好处,不需要减法。
对任意 x − y x-y xy看成 x + ( − y ) x+(-y) x+(y),例如 1 − 127 1-127 1127:
1 − 127 = ( 0000 0001 ) − ( 0111 1111 ) = 1000 0010 = 1 + ( − 127 ) = ( 0000 0001 ) + ( 1000 0001 ) = 1000 0010 1-127=(0000\quad0001) - (0111\quad1111)\\ =1000\quad0010\\ =1+(-127)\\ =(0000\quad0001)+ (1000\quad0001)=1000\quad0010\\ 1127=(00000001)(01111111)=10000010=1+(127)=(00000001)+(10000001)=10000010
做减法的时候如果不够减就向高位借,实在不够就向溢出位借。
总结上述操作就是先定义正数,使用 x + ( − x ) = 0 x+(-x)=0 x+(x)=0的办法来定义对应负数,并且等于零是用数值溢出的办法得到的,计算时将减法转换为加法,同时上述操作符号位也都参与计算。

以上的操作似乎很一致,并且符合直觉。但是有一个数是例外,-128。8bits 补码表示的区间是[-128, 127], +128是没有定义的,-128也就没办法用上述的办法定义。
用补充的办法将这个边界值定义为 1000 0000,试着用上面的办法计算其对应的值,我们发现其对应正值还为1000 0000,也就是说符号为仍为1。所以这个边界值是上述转换方法的一个bug,但是不影响计算,因为符合借位计算的思想,也符合加周期取模的思想。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值