【嵌入式基础小知识】迷惑的补码

1,429 阅读6分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

夫风者,天地之气,溥畅而至,不择贵贱高下而加焉。 《风赋》

一、什么是补码?

聊补码前,要先知道什么是原码?

原码(true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。 简单直观;例如,我们用8位二进制表示一个数,+11的原码为00001011,-11的原码就是10001011。 来源于百度百科-原码:baike.baidu.com/item/原码/109…

和原码一样,补码也是计算机中的一种有符号数表示方法。

补码,英文名叫 2's complement,可直译为“对数字 2 的补充”,是一种用二进制表示有符号数的方法。 对于 2's complement名字的由来,摘录极客时间课程《深入 C 语言和程序运行原理》的部分内容:

我们来计算一下有符号整数 3 对应的四位补码,可以得到一个二进制序列 “0011”。将该二进制序列与上述 -3 对应的二进制序列1101 相加,通过进位可以得到序列 “10000”,该序列可以表示无符号正整数 16。 因此,我们可以得到这样一个结论:对于非负数 x,我们可以用 2^w − x 来计算 −x 的 w 位表示。套用在上述的例子中,可以得到“在四位补码的情况下,对于非负数 3,可以用无符号数 13 (即 16−3) 的位模式来表示有符号数 -3 的位模式”这个结论,即两者位模式相同。而补码的英文名称正是对 x、−x 和 2 w三者之间的关系进行的总结。

值得注意的是:在计算机系统中,数值一律用补码来表示和存储(编程的时候我们可能看不到,那是因为编译器帮我们处理了)。 为什么没有选择原码这种简单直观,符合人类查看的有符号数表示方式呢? 下面就来聊聊补码的优点。

二、补码的优势

  • 最大优点是可以在加法或减法处理中,不需因为数字的正负而使用不同的计算方式。只要一种加法电路就可以处理各种有号数加法,而且减法可以用一个数加上另一个数的补码来表示,因此只要有加法电路及补码电路即可完成各种有号数加法及减法,在电路设计上相当方便。
  • 补码系统的 0 就只有一个表示方式,这和原码、反码系统不同(在反码系统中,0 有二种表示方式),因此在判断数字是否为 0 时,只要比较一次即可。

三、补码与原码的转换

下面说的是有符号数,对于无符号数,原码和补码是一样的。

3.1、知原码,求取补码

3.1.1、求取正数和 0 的补码

正数和 0 的补码就是其自身。(符号位为0的都属于这种)

3.1.2、求取负数的补码

  • 方法一 负数的补码则是将其对应正数按位取反再加1。
  • 方法二(来自维基百科:补码),推荐这种方法,更容易记,因为更接近补码的本质。 在这里插入图片描述

3.2、知补码,求取原码

  • 对于最高位为 0 的补码(0或者正数),其原码为其本身。
  • 如果补码的符号位为 “1”,说明这是一个负数,求取原码的操作为:符号位为1(也就是保持符号位),其余各位取反,然后整个数加1。 当然对于负数,也可以使用如下公式,我们知道 N^*2^n,也就知道了 N,然后把 N 的符号位改成 1 就得到了要求取的负数。(题外话:这个关系也是实现只要有加法电路及补码电路即可完成各种有号数加法及减法的关键) 在这里插入图片描述

四、补码的工作原理(深入必看)

发现维基百科这一段写的很好,直接摘录,虽然有点烧脑,不过理解了肯定对你有很大的收获。

为什么补码能这么巧妙实现了正负数的加减运算?答案是:指定n比特字长,那么就只有 2^n 个可能的值,加减法运算都存在上溢出与下溢出的情况,实际上都等价于模 2^n 的加减法运算。这对于 n 比特无符号整数类型或是 n 比特有符号整数类型都同样适用。

例如,8位无符号整数的值的范围是0到255,因此4+254将上溢出,结果是2,即 (4+254) = 258= 2(mod 256)。

例如,8位有符号整数的值的范围,如果规定为−128到127,则126+125将上溢出,结果是−5,即(126+125) = 251 = -5 (mod 256)。

对于8位字长的有符号整数类型,以 2^8256为模,则 在这里插入图片描述 所以模256下的加减法,用0, 1, 2,…, 254,255表示其值,或者用−128, −127,…, −1, 0, 1, 2,…,127是完全等价的。−128与128,−127与129,…,−2与254,−1与255可以互换而加减法的结果不变。从而,把8位(octet)的高半部分(即二进制的1000 0000到1111 1111)解释为−128到−1,同样也实现了模256的加减法,而且所需要的CPU加法运算器的电路实现与8位无符号整数并无不同。

实际上对于8比特的存储单元,把它的取值[00000000,…, 11111111]解释为[0, 255],或者[-1, 254],或者[-2, 253],或者[-128, 127],或者[-200, 55],甚至或者[500, 755],对于加法硬件实现并无不同。

五、参考资料