什么是补码,怎么求补码

1 前言

我的上一篇文章谈论到在汇编语言中
为什么 SHL 和 SAL 相同,而 SHR 和 SAR 不同
由此产生的疑惑更多了
到底什么是符号位? 进而补码又是什么?

2 为什么要有补码?

理由很简单,计算机内部只有加法器,并没有减法器
所以在计算机中,在我们人类眼中很简单的算术运算 2 - 3 = -1
计算机是无法完成的,那么依照计算机只能做加法,很显然的想到了 2 + (-3) = -1
因此数在计算机中必然要有特定的表示,那么补码就诞生了。

3 什么是补码?

无符号(unsigned)的一个字节的数表示如下:

0000 0000 = 0
0000 0001 = 1
0000 0010 = 2
...
1111 1111 = 255

有符号数(signed)的一个字节的数表示如下:

0000 0000 = 0
0000 0001 = 1
0000 0010 = 2
...
1000 0000 = 0
1000 0001 = -1
...
1111 1111 = -127

问题出现了,0000 00001000 0000 都代表着数字 0 0 0

不仅如此,且计算两个数相加会非常复杂,比如:

    0000 0010
+   1000 1100
---------------
    ???? ????

这必然给计算机运算器带来麻烦
于是约定,将1000 0000 设置为 -128,了解更多 点这里
因此范围被定义为: − 128 -128 128 ≤ \leq X ≤ \leq + 127 +127 +127

虽然两个 0 的表示问题解决了,但是计算问题依旧相当复杂,于是就引进了补码

几乎所有的教材都这样写到:

正数的补码就是原码
负数的补码是符号位不变(1),其余位取反,然后加一

并且给出以下定义:

一个有符号数的最高位为符号位
0 代表这个数为正数
1 代表这个数为负数

依照这种定义,我们简单的来进行几个运算:
【例1】用补码计算 45 + 24

	0010 1101
+   0001 1000
---------------
	0100 0101

正常答案69也是轻而易举的求出来了

【例2】用补码计算45 - 38

    0010 1101
+   1101 1010 
-----------------
(1) 0000 0111

计算这一题的时候就有些犹豫了,因为进位已经到了符号位
那么我的符号位到底参与运算吗?
常理来说,符号位顾名思义,代表着数的正负,怎么可以参与运算呢?
事实却恰恰相反,符号位参与运算的结果才是正确的,如上例所示。

4 什么才是正真的补码?

上述的例子说明了一个非常矛盾的事情
把一个数的最高位定义为了符号位,计算中符号位却能参与运算
想必这也是很多人蒙在鼓里的地方了

补码的定义(以 8 8 8位字长数为例):

表示范围
X X X 0 0 0 ≤ \leq X X X ≤ \leq + 127 +127 +127
2 8 2^8 28- X X X − 128 -128 128 ≤ \leq X X X < 0 <0 <0

也就是说,正数的补码就是原码
而反码的补码等于位数 2 8 2^8 28 减去 X X X 的绝对值 ∣ X ∣ |X| X,例如 − 38 -38 38 的补码:

  1 0000 0000
-   0010 0110
----------------
    1101 1010

所以 − 38 -38 38 的补码为1101 1010

在这种定义下,没有反码的概念,也没有符号位的概念


参考:
[1] Signed Int: Bias/Excess Notation

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值