按位进位应用程序

时间:2017-04-12 09:33:08

标签: c math bit-manipulation bitwise-operators twos-complement

叫我天真,但在这方面我总是挣扎。所以我只是浏览代码,添加了两个不带+运算符的数字,并且碰到了这段代码:

int Add(int x, int y)
{
    // Iterate till there is no carry  
    while (y != 0)
    {
        // carry now contains common set bits of x and y
        int carry = x & y;  

        // Sum of bits of x and y where at least one of the bits is not set
        x = x ^ y; 

        // Carry is shifted by one so that adding it to x gives the 
        // required sum
        y = carry << 1;
    }
    return x;
}

现在我明白了,他是如何计算进位但为什么y!= 0以及这段代码如何实现添加两个数字的结果?

2 个答案:

答案 0 :(得分:3)

首先是基础知识。独占或两位与其总和的底部数字相同。并且“两位”与其总和的最高位相同。

A | B | A&B | A^B | A+B
-----------------------
0 | 0 |  0  |  0  |  00
0 | 1 |  0  |  1  |  01
1 | 0 |  0  |  1  |  01
1 | 1 |  1  |  0  |  10

如您所见,独占或结果与总和的最后一位相同。当A为1且B为1时,您还可以看到总和的第一个数字仅为1.

[如果你有一个带有两个输入和两个输出的电路,其中一个是输入的exclusive or,另一个是输入的and,它被称为半加法器 - 因为没有设施也输入一个进位(来自前一个数字)。]

因此,要将两位相加,您需要计算XOR以获得结果的最低位,并计算AND以获得结果的最高位。

对于一对数字中的每个单独的位对,我可以通过执行XOR和AND来计算这两位的总和。使用四位数,例如3和5

3 0011
5 0101
------
  0110 3^5 = 6 (low bit)
  0001 3&5 = 1 (high bit)

为了将3和5视为单个数而不是4个比特的集合,需要将这些高位中的每一个视为进位并将其添加到左侧的下一个低位。我们可以通过将3&amp; 5左移1位并添加到我们通过重复两次操作所做的3 ^ 5来实现这一点

6    0110
1<<1 0010
     ----
     0100 6^(1<<1) = 4
     0010 6&(1<<1) = 2

不幸的是,其中一项添加导致另一个进位产生。所以我们可以重复一下这个操作。

4    0100
2<<1 0100
     ----
     0000 4^(2<<1) = 0
     0100 4&(2<<1) = 4

我们仍然有一个进位,所以我们再来一次。

0    0000
4<<1 1000
     ----
     1000 4^(4<<1) = 8
     0000 4&(4<<1) = 0

这一次,所有的进位都是0,因此更多的迭代不会改变任何东西。我们已经完成了。

答案 1 :(得分:0)

我将尝试在一个简单的3位示例上解释它(您可以跳过此示例到以粗体字体标记的实际说明,并从开始到现在我们从发布的代码实现相同流程的方式< / em>的)。

假设我们想要添加x = 0b011,其中y = 0b101。首先,我们添加最低有效位1+1 = 0b10

carry: x10
x:     011
      +
y:     101
      -----
       xx0

然后我们添加第二位(我们需要在书中添加前一阶段的进位,但我们也可以在以后阶段跳过它):1+0 = 0b1

carry: 010
x:     011
      +
y:     101
      -----
       x10

对第三位执行相同操作:0+1 = 0b1

carry: 010
x:     011
      +
y:     101
      -----
       110

现在我们有carry = 0b010和部分结果0b110。 还记得我之前的评论,我们会在稍后的某个阶段照顾好吗?所以现在是这个&#34;后期&#34;。现在我们将进位添加到我们得到的部分结果中(注意,如果我们在前面的阶段分别为每个位添加进位,则它是相同的)。 LSB位加法:

NEW carry:    x00
carry:        010
             +
part. res.:   110
             -----
              xx0

第二位加法:

NEW carry:    100
carry:        010
             +
part. res.:   110
             -----
              x00

第三位加法:

NEW carry:      100
carry:          010
               +
part. res.:     110
               -----
new part. res.  100

现在carry = NEW carry, part. res. = new part. res.,我们再次进行相同的迭代。

对于LSB

NEW carry:    x00
carry:        100
             +
part. res.:   100
             -----
              xx0

第二位:

NEW carry:    000
carry:        100
             +
part. res.:   100
             -----
              x00

第三位:

NEW carry:   1000 --> 000 since we are working with 3 bits only
carry:        100
             +
part. res.:   100
             -----
              000

现在NEW carry为0所以我们已完成计算。最终结果是0b000(溢出)。

我相信我在这里找不到任何东西。 现在我们从发布的代码中获得相同的流程:

partial result是没有carry的结果,这意味着当xy在同一位置有不同的位时,这些位的总和将为1如果相同的位相同,则结果将为0(1 + 1 =&gt; 0,carry 1和0 + 0 =&gt; 0,carry 0)。

因此部分结果x ^ y(请参阅XOR operation的属性)。在发布的代码中,它是x = x ^ y;

现在让我们看一下carry。只有当两个位都为1时,我们才会从单个位加法中获得进位。因此,将进位位设置为1的位在以下表达式中标记为1:x & y(仅在同一位置设置位)将保持1)。 但是应该将进位添加到下一个(更重要的)位!因此

carry = (x & y) << 1; // in the posted code it is y = carry << 1

除非carry为0,否则将执行迭代(如我们的示例所示)。