Eric's Studio

2's complement

Word count: 1kReading time: 3 min
2024/03/22

师傅引进门,修行在个人。一个简简单单的补码,居然又让我水了一篇分享文。

最近在 Debug 的时候断点处理了一些和 Proto 相关的数据。

IDE 展示的 Byte 数组的内容是有符号十进制数据,不方便和 xxd 读取的原始数据进行对比。

依稀记得好像是有个什么右键菜单可以把数据按照 16 进制的格式进行展示,后来发现可以在 IDE 中设置 Show hex value for primitives 就可以在 Debug 的时候直接展示 16 进制的数据了。

解决完这个问题之后突然又对 Byte 数据转换成十进制有符号数的逻辑产生了兴趣,试着手动转换了一下。

我们上专业课的时候学到,在计算机的体系中,为了简化运算的复杂度,我们使用补码对数据进行存储和计算。

对于补码,我们有两条认知

  1. 正数的补码等于其本身
  2. 负数的补码需要取负数的绝对值,接下来转换为二进制格式,按位取反,结果再加一

在我所接受的专业课教育中,关于补码的说明就到此为止了,我们按图索骥的运算一番发现确实如此,可以用补码相加的结果忽略掉溢出的位得到减法的运算结果。

但是为什么呢?在毕业若干年后,我对自己问出了这样的问题。问题的关键在哪里,底层的逻辑又在哪里?

首先我问了 devv.ai 想让 AI 给我解释其中的数学原理,不幸的是,我被绕晕了。果然解决编程问题的 AI 还是不太适合当数学老师。

不过在问问题的过程中,我发现了一个新问题:为什么补码要叫做补码?补了谁?又是什么码?

于是我又查了维基百科,敏锐的发现了补码的英文名称 2's complement 湾湾叫二补数,港澳叫二补码。

大陆是谁起的名字,出来挨打。

通过补码这个词条,我又找到了补数这个词条:

对于给定的进位制,相加后能使自然数 a 的位数增加 1 的最小的数。

到这里,补了谁,又是什么码,这两个问题就清楚了:

  • 补了 a,结果可以产生进位。
  • 进位制是 2,又称 二维码 二补码

接下来,就是数学问题了,这个通过加法来计算减法的算法,底层是个什么数学公式呢?

我请教了可能更加适合作为老师的 GPT,得到了下面的答案。

首先,我们需要了解补码的计算方法。对于一个n位的二进制数,它的补码定义为2^n(模的基数)减去这个数。也就是说,如果有一个数A,那么它的补码是2^n - A。

补码的数学证明:
假定我们有两个正整数A和B,他们的二进制表示长度都是n位,我们想要计算的是A减去B的结果,即A - B。

在补码的系统中,B的补码表示为2^n - B。

根据补码系统的规则,A - B这个运算可以通过将A与B的补码相加来实现,但是我们只考虑n位的结果,忽略掉溢出的位。所以操作如下:

A + (2^n - B) = A - B + 2^n

因为我们只保留结果的n位,忽略了溢出的部分(也就是忽略了加上的2^n这一项),所以最终得到的结果实际上为A - B。

清晰明了。

我的感受如下:

  1. 现阶段的 AI 确实是提高学习效率的一大利器
  2. 下个阶段的 AI 起码离取代我是不远了

所以我接受的教育,只教了,而没有讲清楚。不知道是不是孤例。

CATALOG