3

我终于知道了补码的意义

 2 years ago
source link: https://blog.vvzero.com/2020/11/18/May-be-I-know-why-use-complement/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文供初学者学习,供大佬批判。

很久很久以前,当我参加 NOIP(信息学奥林匹克竞赛)的时候,老师是这么讲补码的:

int 型数据的最高位是符号位,符号位为 0 就代表这是正数,为 1 就是负数。但是,+0 和 -0 理应是同一个数,但在二进制中却表示成了两个不同的数(以 8 位为例,二进制表示): 00000000 和 10000000。所以,我们引入了补码,补码就是,对负数而言,符号位不变,其他位取反,然后再加 1。于是, -0 的补码就是 10000000 -> 11111111 -> 00000000 与 +0 一致了。

补码的意义

其实当时我就该意识到,仅仅为了 0 这一个数便创建了“补码”这个概念,未免太浪费了。我最近看了 CS: APP 这本书,才进一步理解了补码。

补码,就是为有符号整数而创建的概念。对于无符号整数,是不存在“补码”的概念的。我们先看一个无符号数 00100101,它是怎么转换成十进制的?加权求和,0×2^7+0×2^6+1×2^5+0×2^4+0×2^3+1×2^2+0×2^1+1×2^0=37;无符号数 10000011,1×2^7+0×2^6+0×2^5+0×2^4+0×2^3+0×2^2+1×2^1+1×2^0=131

对于有符号数呢?假如我们不用补码,那么有符号数 10000011,就是 -(0×2^6+0×2^5+0×2^4+0×2^3+0×2^2+1×2^1+1×2^0)=-3。人这么算起来是挺舒服,但是计算机会很难受,凭什么我最高位的权值没了?只能做符号?

然后我们试试补码。10000011 的补码是 11111101,如何用补码求它的十进制呢?其实这跟无符号数是一样的,只不过,最高位的权值,不是 2^7,而是 -2^7。求值:1×(-2^7)+1×2^6+1×2^5+1×2^4+1×2^3+1×2^2+0×2^1+1×2^0=-3,是不是很神奇?

对于正数而言,就更简单了,与无符号数一致。

计算机只能做加法(不是),所以,我们看看用补码做加法,有什么好处。

先计算 -13+10 吧,很简单的二进制竖式加法:

7 6 5 4 3 2 1 0 1 1 1 1 0 0 1 1 0 0 0 0 1 0 1 0 1 1 1 1 1 1 0 1

11111101 即为 -3 的补码。

再算一个,-8+9:

7 6 5 4 3 2 1 0 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1

神奇吗?最高位的 0 不见了,变成正数 1 了。

补码,就是计算机内部有符号数的存储方式,我们不要认为补码是由原码“转换”而来的,补码本来就代表了实际的数字,11111101 == -3,就这样。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK