【问题标题】:What is “2's Complement”?什么是“2的补码”?
【发布时间】:2010-11-06 04:33:10
【问题描述】:

我正在学习计算机系统课程,并且一直在努力,部分原因是 Two's Complement。我想理解它,但我读过的所有内容并没有为我带来图片。我已经阅读了wikipedia article 和其他各种文章,包括my text book

因此,我想开始这篇社区 wiki 帖子,以定义什么是二进制补码、如何使用它以及它如何在强制转换等操作期间影响数字(从有符号到无符号,反之亦然) , 按位运算和位移运算。

我希望的是一个清晰简洁的定义,程序员很容易理解。

【问题讨论】:

  • 我认为对我有帮助的评论是补码类似于逆,但它没有给出0,而是给出2^N(根据定义),例如数字A 有 3 位,我们想要A+~A=2^N 所以010 + 110 = 1000 = 82^3。至少这澄清了“补语”这个词在这里的含义,因为它不仅仅是 01 含义的反转。有用的麻省理工学院视频:youtube.com/watch?v=RbJV-g9Lob8
  • 一个快速的助记符,也是一个更清晰的混淆:就像符号幅度表示一样,二进制补码表示也有一个“符号位”。因此,要找到一个二进制补码有符号(负、零或正)数的值,只需负数计算最高有效位的符号位,然后将照常计算其余位(正数,就像在无符号编码中一样)。感谢Mr.Brayant 和Mr.O'Hallaron 撰写了令人惊叹的书“计算机系统:程序员的视角”(注意:这本书不仅仅是这个简单的示例)。

标签: binary bit-manipulation computer-science twos-complement data-representation


【解决方案1】:

Two's complement 是一种巧妙的整数存储方式,因此常见的数学问题很容易实现。

要理解,您必须考虑binary 中的数字。

它基本上是说,

  • 对于零,使用全 0。
  • 对于正整数,开始向上计数,最多为 2(位数 - 1)-1。
  • 对于负整数,执行完全相同的操作,但切换 0 和 1 的角色并倒计时(因此,不要从 0000 开始,而是从 1111 开始 - 这是“补码”部分)。

让我们用一个 4 位的 mini-byte 试试(我们称它为 nibble - 1/2 个字节)。

  • 0000 - 零
  • 0001 - 一个
  • 0010 - 两个
  • 0011 - 三
  • 01000111 - 四到七

这就是我们所能做的积极的事情。 23-1 = 7.

对于否定:

  • 1111 - 负一
  • 1110 - 负二
  • 1101-负三
  • 11001000 - 负四到负八

请注意,您会得到一个额外的负值 (1000 = -8),而正值则没有。这是因为0000 用于零。这可以认为是Number Line 的计算机。

区分正数和负数

这样做,第一位获得“符号”位的作用,因为它可以用来区分非负和负十进制值。如果最高位是1,那么二进制可以说是负数,而最高位(最左边)是0,可以说十进制值是非负数。

"Sign-magnitude" 负数只是将其正数对应的符号位翻转,但这种方法必须处理将1000(一个1 后跟所有0s)解释为“负零”,即令人困惑。

"Ones' complement" 负数只是其正数的位补码,这也会导致与 1111(全为 1)混淆的“负零”。

除非您的工作非常接近硬件,否则您可能不必处理 Ones' Complement 或 Sign-Magnitude 整数表示。

【讨论】:

  • 二进制补码的最佳部分可能是它如何简化数学。尝试将 2 (0010) 和 -2 (1110) 相加,得到 10000。最高有效位溢出,因此结果实际上是 0000。几乎就像魔术一样,2 + -2 = 0。
  • 除了简单的加减法之外的另一个优点是2s补码只有一个零。如果您使用简单的符号位,例如使用 0001 表示 +1 和 1001 表示 -1,您将有两个零:0000(“+0”)和 1000(“-0”)。这真是背后的痛苦。
  • 赞成这一点,并解释为什么负值比正值具有更大的范围。我来寻找范围差异的原因。
  • 你不应该说“对于负整数,做完全相同的事情,但倒计时并切换0和1的角色”
  • 太棒了。添加了将位转换为负整数的额外部分。
【解决方案2】:

我想知道它是否可以比维基百科的文章更好地解释。

您试图用二进制补码表示解决的基本问题是存储负整数的问题。

首先,考虑一个存储在 4 位中的无符号整数。您可以拥有以下

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

这些是无符号的,因为没有迹象表明它们是负数还是正数。

符号幅值和超出符号

要存储负数,您可以尝试多种方法。首先,您可以使用符号幅度表示法,它将第一位作为符号位表示 +/-,其余位表示幅度。所以再次使用 4 位并假设 1 表示 - 并且 0 表示 + 那么你有

0000 = +0
0001 = +1
0010 = +2
...
1000 = -0
1001 = -1
1111 = -7

那么,你看到那里的问题了吗?我们有正数和负数 0。更大的问题是二进制数的加减法。使用符号幅度进行加减运算的电路会非常复杂。

什么是

0010
1001 +
----

?

另一个系统是excess notation。你可以存储负数,你摆脱了两个零的问题,但加减法仍然很困难。

随之而来的是二进制补码。现在您可以存储正整数和负整数并相对轻松地执行算术运算。有许多方法可以将数字转换为二进制补码。这是一个。

将十进制转换为二进制补码

  1. 将数字转换为二进制(暂时忽略符号) 例如5 是 0101,-5 是 0101

  2. 如果数字是正数,那么你就完成了。 例如5 是二进制的 0101,使用二进制补码表示法。

  3. 如果是负数,那么

    3.1 求补码(反转 0 和 1) 例如-5 是 0101 所以找到补码是 1010

    3.2 补码 1010 + 1 = 1011 加 1。 因此,二进制补码中的 -5 是 1011。

那么,如果你想在二进制中做 2 + (-3) 怎么办? 2 + (-3) 为 -1。 如果您使用符号幅度来添加这些数字,您会怎么做? 0010 + 1101 = ?

考虑使用二进制补码有多容易。

 2  =  0010
 -3 =  1101 +
 -------------
 -1 =  1111

将二进制补码转换为十进制

将 1111 转换为十进制:

  1. 数字以1开头,所以是负数,所以我们求1111的补码,即0000。

  2. 0000加1,得到0001。

  3. 将 0001 转换为十进制,即 1。

  4. 应用符号 = -1。

多田!

【讨论】:

  • 我认为的最佳答案。
  • 是的,这个很简单,解释的很好
  • 我不明白如何在两种方式转换时添加一个总是导致相同的数字。在我看来,你会颠倒这些步骤,或者减去一个或一些东西。
  • 为什么补码加1?
  • 这个答案应该用在维基百科上。
【解决方案3】:

就像我见过的大多数解释一样,上面的解释清楚地说明了如何使用 2 的补码,但并没有真正从数学上解释它们 是什么。我会尝试这样做,至少对于整数,我会先介绍一些可能很熟悉的背景。

回想一下它是如何处理十进制的:
  2345
是一种书写方式
  2 × 103 + 3 × 102 + 4 × 101 + 5 × 100.

同样,二进制是一种仅使用 01 的数字书写方式,遵循相同的总体思路,但将上面的 10 替换为 2。那么在二进制中,
  1111
是一种写法
  1 × 23 + 1 × 22 + 1 × 21 + 1 × 20
如果你算出来,结果等于 15(以 10 为底)。那是因为它是
  8+4+2+1 = 15。

这对正数来说很好。如果你愿意在负数前面加上一个减号,它甚至适用于负数,就像人类对十进制数所做的那样。这甚至可以在计算机中完成,有点,但自 1970 年代初以来我还没有见过这样的计算机。我将留下不同讨论的原因。

对于计算机,使用 补码 表示负数会更有效。这是经常被忽视的东西。补码符号涉及数字的某种反转,甚至是在正常正数之前的隐含零。这很尴尬,因为问题出现了:所有这些?这可能是要考虑的无限位数。

幸运的是,计算机并不代表无限。数字被限制为特定的长度(或宽度,如果您愿意)。所以让我们回到正二进制数,但具有特定的大小。对于这些示例,我将使用 8 位数字(“位”)。所以我们的二进制数真的是
  00001111

  0 × 27 + 0强> × 26 + 0 × 25 + 0 × 24 + 1 × 23 + 1 × 22 + 1 × 21 + 1 × 20

为了形成 2 的补码负数,我们首先对所有(二进制)数字进行补码以形成
  11110000
然后加 1 以形成
  11110001
但我们如何理解这意味着 -15?

答案是我们改变了高位(最左边的位)的含义。对于所有负数,该位将为 1。改变将是改变它对它出现的数值的贡献的符号。所以现在我们的 11110001 被理解为代表
  -1 × 2 7 + 1 × 26 + 1 × 25 + 1 × 24 + 0 × 23 + 0 × 22 + 0 × 21 + 1 × 20
注意到那个表达式前面的“-”了吗?这意味着符号位的权重为-27,即-128(以10为底)。所有其他位置都保持与无符号二进制数相同的权重。

计算出我们的 -15,它是
-128 + 64 + 32 + 16 + 1
在你的计算器上试试。现在是 -15。

在我见过的计算机中表示负数的三种主要方式中,为了方便一般使用,2 的补码胜出。不过,它有一个奇怪的地方。由于它是二进制的,因此必须有偶数个可能的位组合。每个正数都可以与其负数配对,但只有一个零。否定一个零会让你为零。所以还有一个组合,符号位中带有 1 的数字和其他任何地方都带有 0 的数字。相应的正数不适合正在使用的位数。

这个数字更奇怪的是,如果你试图通过补加一个来形成它的正数,你会得到相同的负数。零会这样做似乎很自然,但这是出乎意料的,根本不是我们习惯的行为,因为除了计算机之外,我们通常认为数字的无限供应,而不是这种固定长度的算术。

这只是怪事的冰山一角。表面之下还有更多的等待,但这对于这次讨论来说已经足够了。如果您研究定点算术的“溢出”,您可能会发现更多。如果你真想深入,还可以研究一下“模运算”。

【讨论】:

  • 我喜欢这个答案!解释取 2s 补码和加 1 的工作原理。
  • 我也喜欢这个答案。尤其是在您展示如何计算负数的地方。在这里,我认为整数是倒置的,而不仅仅是 MSB,然后加回其他加权值。谢谢,这解决了我的大脑障碍
  • 很好地提到了没有倒数的奇数。但是我们该怎么做呢?如果有人试图反转它,我们是否只设置溢出标志?
  • 当其他答案集中在“如何”上时,这个答案会轻轻地引导我们“为什么”。它帮助了我。谢谢!
  • 如果一个数字以 11000...000 结尾,反转它会得到 01000...000。二进制补码表示法基于这样一种想法,即最左边表示的数字左侧的所有数字都应具有与该数字相同的值,但是当反转表示为 1000...000 的数字时,这将不正确。
【解决方案4】:

2 的补码对于查找二进制的值非常有用,但是我想到了一种更简洁的方法来解决此类问题(从未见过其他人发表过):

取一个二进制,例如:1101 [假设空格“1”是符号]等于-3

使用 2 的补码我们会这样做...将 1101 翻转到 0010...添加 0001 + 0010 ===> 给我们 0011。0011 正二进制 = 3。因此 1101 = -3

我意识到的:

而不是所有的翻转和添加,你可以做一个基本的方法来解决一个正二进制(比如说 0101)是 (23 * 0) + (22 * 1) + (21 * 0) + (20 * 1) = 5。

用否定做完全相同的概念!(稍微扭曲)

以1101为例:

对于第一个数字,而不是 23 * 1 = 8 ,执行 -(23 * 1) = - 8.

然后像往常一样继续,做 -8 + (22 * 1) + (21 * 0) + (20 * 1) = -3

【讨论】:

  • 最好的办法,我能理解 2 的补码。看完这篇,我可以理解上述问题的所有答案了。
  • 这是《计算机系统:程序员的视角》一书中提到的方法。
  • 这是一个更快的方法!
【解决方案5】:

想象一下,您有有限数量的位/trits/digits/whatever。您将 0 定义为所有数字为 0,并自然向上计数:

00
01
02
..

最终你会溢出。

98
99
00

我们有两位数,可以表示从 0 到 100 的所有数字。所有这些数字都是正数!假设我们也想表示负数?

我们真正拥有的是一个循环。 2前面的数字是1。1前面的数字是0。0前面的数字是……99

因此,为简单起见,假设任何超过 50 的数字都是负数。 “0”到“49”代表0到49。“99”是-1,“98”是-2,...“50”是-50。

这种表示是十的补码。计算机通常使用二的补码,除了使用位而不是数字之外,它是相同的。

十的补码的好处是加法很有效。你不需要做任何特殊的事情来添加正数和负数!

【讨论】:

    【解决方案6】:

    我阅读了 jng 的精彩解释 on Reddit,使用里程表作为类比。

    这是一个有用的约定。相同的电路和逻辑操作 在二进制中加/减正数仍然适用于正数 如果使用约定,则为负数,这就是它的原因 有用且无所不在。

    想象一下汽车的里程表,它在(比如说)99999 处滚动。如果你 增加 00000 你得到 00001。如果你减少 00000,你得到 99999 (由于滚动)。如果您将 1 添加回 99999 它会返回 00000。因此确定 99999 代表 -1 很有用。同样,决定 99998 代表 -2 也非常有用,以此类推。你有 停在某个地方,并且按照惯例,停在数字的上半部分 被认为是负数(50000-99999),下半部分是正数 只是代表自己(00000-49999)。结果,上位数字 为 5-9 表示表示的数字为负数,为 0-4 表示表示为正 - 与最高位完全相同 用二进制补码表示符号。

    我也很难理解这一点。一旦我得到它并回到 重新阅读书籍文章和解释(没有互联网 那时),事实证明很多描述它的人并不是真的 明白它。之后我确实写了一本书教汇编语言 那个(10 年来确实卖得很好)。

    【讨论】:

    • 哇,我已经 很长 看到了速度和公里/小时的速度。澳大利亚在我达到 10 岁之前就切换了,我仍然记得当他试图在 100 公里/小时的区域内以 100 英里/小时的速度行驶时,我必须提醒老人(俚语:父亲)基本的转换:-)跨度>
    • 无论如何,我认为他们在某个时候停止允许 odo 回滚。将其与汽车断开连接并使用钻头将其回滚是(一些相当狡猾的)人们在尝试以较低里程出售汽车时最喜欢的技巧(有趣的是,我们仍然使用该术语,猜测公里数从未流行)。
    【解决方案7】:

    通过将给定数字的第一个补码加一来找到两个补码。 假设我们要找出10101的补码,然后找到它的补码,即01010在这个结果上加上1,即01010+1=01011,这就是最终的答案。

    【讨论】:

      【解决方案8】:

      让我们使用 8 位以二进制形式得到答案 10 – 12: 我们真正要做的是 10 + (-12)

      我们需要得到 12 的恭维部分以从 10 中减去它。 二进制的 12 是 00001100。 二进制的10是00001010。

      为了得到 12 的互补部分,我们只需将所有位反转然后加 1。 12 的二进制反转是 11110011。这也是反码(一个补码)。 现在我们需要添加一个,现在是 11110100。

      所以 11110100 是 12 的恭维!这样想就容易了。

      现在你可以用二进制形式解决上面的问题 10 - 12。

      00001010
      11110100
      -----------------
      11111110  
      

      【讨论】:

        【解决方案9】:

        从数学的角度来看二进制补码系统确实很有意义。在十的补码中,这个想法基本上是“隔离”差异。

        示例:63 - 24 = x

        我们添加 24 的补码,实际上就是 (100 - 24)。所以说真的,我们所做的只是在等式两边都加 100。

        现在等式是:100 + 63 - 24 = x + 100,这就是我们删除 100(或 10 或 1000 或其他)的原因。

        由于必须从一长串零中减去一个数字的不便情况,我们使用“递减基数补码”系统,在十进制系统中,九的补码。

        当我们看到一个从一长串九中减去的数字时,我们只需要将这些数字颠倒即可。

        示例:99999 - 03275 = 96724

        这就是原因,在 9 的补码之后,我们加 1。您可能从小时候的数学中知道,9 通过“偷”1 变成 10。所以基本上它只是 10 的补码,从差中取 1。

        在二进制中,二的补码等于十的补码,而一的补码等于九的补码。主要区别在于,我们尝试用 2 的幂来隔离差异,而不是尝试用 10 的幂(将 10、100 等添加到等式中)来隔离差异。

        正是出于这个原因,我们反转了位。就像我们的被减数是十进制的九链一样,我们的被减数是二进制的一链。

        示例:111111 - 101001 = 010110

        因为 1 的链比 2 的幂次方低 1,所以它们从差值中“窃取”1,就像 9 在十进制中所做的那样。

        当我们使用负二进制数时,我们实际上只是在说:

        0000 - 0101 = x

        1111 - 0101 = 1010

        1111 + 0000 - 0101 = x + 1111

        为了“隔离”x,我们需要添加 1,因为 1111 与 10000 相差一个,并且我们删除了前导 1,因为我们只是将它添加到原始差异中。

        1111 + 1 + 0000 - 0101 = x + 1111 + 1

        10000 + 0000 - 0101 = x + 10000

        两边去掉10000就可以得到x,这是基本代数。

        【讨论】:

          【解决方案10】:

          到目前为止,许多答案都很好地解释了为什么使用二进制补码来表示负数,但没有告诉我们二进制补码是什么,尤其是为什么要添加“1”,实际上经常添加错误方式。

          混淆来自于对补数的定义缺乏了解。补语是使某事变得完整的缺失部分。

          根据定义,基数 b 中的 n 位数字 x 的基数补码是 b^n-x。 在二进制中,4 由 100 表示,它有 3 位数字 (n=3) 和一个基数 2 (b=2)。所以它的基数补码是 b^n-x = 2^3-4=8-4=4 (或二进制的 100)。

          然而,在二进制中获得一个基数的补码并不像获得其减少的基数补码那样容易,它被定义为 (b^n-1)-y,仅比基数补码少 1。要获得减少的基数补码,只需翻转所有数字即可。

          100 -> 011(减少的(一个)基数补码)

          要获得基数(二进制)补码,我们只需按照定义添加 1。

          011 +1 ->100(二进制补码)。

          现在有了这个新的认识,让我们看看下面给出的例子 文森特·拉姆达尼(见上文第二个回复)

          /* 文森特的开始

          将 1111 转换为十进制:

          数字以 1 开头,所以是负数,所以我们找到 1111 的补码,也就是 0000。 0000 加 1,得到 0001。 将 0001 转换为十进制,即 1。 应用符号 = -1。 多田!

          文森特结束 */

          应该理解为

          数字以 1 开头,所以是负数。所以我们知道它是某个值 x 的二进制补码。要找到 x 的补码表示的 x,我们首先需要找到它的 1 的补码。

          x 的补码:1111 x的补码:1111-1 -> 1110; x = 0001,(翻转所有数字)

          应用符号 -,答案 =-x =-1。

          【讨论】:

            【解决方案11】:

            补语源于完整性。在十进制世界中,数字 0 到 9 提供了数字或数字符号的补码(完整集)来表示所有十进制数。在二进制世界中,数字 0 和 1 提供了数字的补码来表示所有二进制数。事实上,符号 0 和 1 必须用于表示一切(文本、图像等)以及正 (0) 和负 (1)。 在我们的世界里,数字左边的空格被认为是零:

                              35=035=000000035.
            

            在计算机存储位置中没有空白空间。所有位(二进制数字)必须为 0 或 1。为了有效地使用内存,数字可以存储为 8 位、16 位、32 位、64 位、128 位表示。当存储为 8 位数字的数字传输到 16 位位置时,符号和大小(绝对值)必须保持不变。 1 的补码和 2 的补码表示都促进了这一点。 作为名词: 1 的补码和 2 的补码都是有符号量的二进制表示,其中最高有效位(左侧的一位)是符号位。 0 表示正,1 表示负。 2s 补码不代表否定。这意味着有符号的数量。在十进制中,大小表示为正数。当提升到具有更多位的寄存器 [] 时,该结构使用符号扩展来保留数量:

                   [0101]=[00101]=[00000000000101]=5 (base 10)
                   [1011]=[11011]=[11111111111011]=-5(base 10)
            

            作为动词: 2 的补码表示否定。这并不意味着否定。这意味着如果负数变为正数;如果正面则为负面。幅度是绝对值:

                    if a >= 0 then |a| = a
                    if a < 0 then |a| = -a = 2scomplement of a
            

            此功能允许使用先求后加的高效二进制减法。 a - b = a + (-b)

            取 1 的补码的官方方法是每个数字从 1 中减去它的值。

                    1'scomp(0101) = 1010.
            

            这与单独翻转或反转每个位相同。这导致负零不受欢迎,因此将 1 添加到 te 1 的补码可以解决问题。 要取反或取 2s 补码,请先取 1s 补码,然后加 1。

                    Example 1                             Example 2
                     0101  --original number              1101
                     1's comp  1010                       0010
                     add 1     0001                       0001
                     2's comp  1011  --negated number     0011
            

            在示例中,否定也适用于符号扩展数字。

            添加:
            1110 进位 111110 进位 0110 与 000110 相同 1111 111111 总和 0101 总和 000101

            减法:

                1110  Carry                      00000   Carry
                 0110          is the same as     00110
                -0111                            +11001
              ----------                        ----------
            sum  0101                       sum   11111
            

            请注意,在使用 2 的补码时,数字左侧的空白区域用零填充正数,但用 1 填充负数。进位总是被添加,并且必须是 1 或 0。

            干杯

            【讨论】:

              【解决方案12】:

              2 的补码本质上是一种求出二进制数的加法倒数的方法。问问自己:给定一个二进制形式的数字(存在于固定长度的内存位置),当添加到原始数字(在固定长度的内存位置)时,什么样的位模式会使结果全为零? (在相同的固定长度内存位置)。如果我们能想出这个位模式,那么那个位模式将是原始数字的 -ve 表示(加法逆);根据定义,将一个数字添加到其加法逆元总是会导致零。示例:取 5,即 101 存在于单个 8 位字节中。现在的任务是提出一个位模式,当添加到给定的位模式 (00000101) 将导致用于保存这 5 的内存位置全为零,即所有 8 位字节应该为零。为此,从最右边的 101 位开始,对于每个单独的位,再次问同样的问题:我应该在当前位上添加什么位以使结果为零?考虑到通常的结转,继续这样做。在我们完成了最右边的 3 个位置(定义原始数字而不考虑前导零的数字)之后,最后一个进位进入加法逆的位模式。此外,由于我们将原始数字保存在单个 8 位字节中,加法逆运算中的所有其他前导位也应该是 1,因此(这很重要)当计算机添加“数字”(使用 8位模式)及其使用“那个”存储类型(一个字节)的加法逆运算,结果在那个字节中将全为零。

               1 1 1
               ----------
                 1 0 1
               1 0 1 1 ---> additive inverse
                ---------
                 0 0 0
              

              【讨论】:

                【解决方案13】:

                我喜欢 lavinio 的回答,但移位会增加一些复杂性。通常可以选择在尊重符号位或不尊重符号位的情况下移动位。这是将数字视为有符号(半字节为 -8 到 7,字节为 -128 到 127)或全范围无符号数字(半字节为 0 到 15,字节为 0 到 255)之间的选择。

                【讨论】:

                  【解决方案14】:

                  这是一种对负整数进行编码的巧妙方法,它使数据类型的大约一半的位组合保留给负整数,并且将大多数负整数与其对应的正整数相加会导致进位溢出,结果为二进制零。

                  所以,在 2 的补码中,如果一个是 0x0001,那么 -1 就是 0x1111,因为这将导致组合总和为 0x0000(溢出为 1)。

                  【讨论】:

                    【解决方案15】:

                    2 的补码:当我们用一个数字的 1 的补码添加一个额外的数字时,我们将得到 2 的补码。例如:100101 1 的补码是 011010,2 的补码是 011010+1 = 011011(1 的补码加一)For more information 本文以图形方式解释。

                    【讨论】:

                    • 加 1 链接有圆圈说明
                    【解决方案16】:

                    简单来说2's Complement 是一种在计算机内存中存储负数的方法。而正数存储为普通二进制数。

                    让我们考虑这个例子,

                    计算机使用Binary Number System 表示任意数字。

                    x = 5;
                    

                    这表示为0101

                    x = -5;
                    

                    当计算机遇到- 符号时,它计算它的2 的补码并存储它。 i.e 5 = 0101 其 2 的补码是 1011

                    计算机用来处理数字的重要规则是,

                    1. 如果第一位是1,那么它必须是negative 数字。
                    2. 如果除第一位以外的所有位都是0,那么它是一个正数 因为数字系统中没有-0。(1000 is not -0 而是正数8
                    3. 如果所有位都是0,那么它就是0
                    4. 否则它是positive number

                    【讨论】:

                      【解决方案17】:

                      二进制补码是表示负数的一种方式,大多数控制器和处理器都以 2 的补码形式存储负数

                      【讨论】:

                      • 这不会对其他答案提供的信息添加任何内容。
                      【解决方案18】:

                      二进制补码主要用于以下原因:

                      1. 为了避免 0 的多重表示
                      2. 避免在发生溢出时跟踪进位位(如反码)。
                      3. 加减法等简单运算变得容易。

                      【讨论】:

                        【解决方案19】:

                        参考:https://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html

                        我将所有位反转并加 1。以编程方式:

                          // in C++11
                          int _powers[] = {
                              1,
                              2,
                              4,
                              8,
                              16,
                              32,
                              64,
                              128
                          };
                        
                          int value=3;
                          int n_bits=4;
                          int twos_complement = (value ^ ( _powers[n_bits]-1)) + 1;
                        

                        【讨论】:

                        • 即使是汇编程序也太高级了。需要查看加法逻辑的门级示意图。有 T 个循环。你在算法上是正确的。
                        【解决方案20】:

                        给定数字的 2 的补码是编号。通过将 1 与编号的 1 的补码相加得到。 假设,我们有一个二进制数:10111001101 它的 1 的补码是:01000110010 它的 2 的补码将是:01000110011

                        【讨论】:

                          【解决方案21】:

                          对一个数字进行按位补码就是翻转其中的所有位。为了补码,我们翻转所有位并加一。

                          使用 2 的补码表示有符号整数,我们应用 2 的补码运算将正数转换为负数,反之亦然。因此,以半字节为例,0001 (1) 变为 1111 (-1) 并再次应用操作,返回到 0001

                          在零处的操作行为有利于为零提供单一表示,而无需对正零和负零进行特殊处理。 0000 补充了 1111,当添加 1 时。溢出到0000,给我们一个零,而不是一个正数和一个负数。

                          这种表示的一个关键优势是无符号整数的标准加法电路在应用于它们时会产生正确的结果。例如在半字节中添加 1 和 -1:0001 + 1111,位溢出寄存器,留下0000

                          为了温和的介绍,出色的 Computerphile 制作了video on the subject

                          【讨论】:

                            【解决方案22】:

                            问题是“什么是“2 的补码”?对于那些想从理论上理解它的人来说简单的答案(我也在寻求补充其他更实际的答案):2 的补码是对偶系统中负整数的表示,不需要额外的字符,例如 + 和 -。

                            【讨论】:

                              【解决方案23】:

                              您还可以使用在线计算器计算十进制数的二进制补码表示:http://www.convertforfree.com/twos-complement-calculator/

                              【讨论】:

                                【解决方案24】:

                                最简单的答案:

                                1111 + 1 = (1)0000。所以 1111 必须是 -1。然后 -1 + 1 = 0。

                                对我来说理解这些是完美的。

                                【讨论】:

                                • 这没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
                                • 这是答案。最简单的。对我来说 - 最好的。
                                猜你喜欢
                                • 2013-05-19
                                • 2016-04-23
                                • 1970-01-01
                                • 2010-12-12
                                • 1970-01-01
                                • 2011-10-14
                                相关资源
                                最近更新 更多