需要澄清这个循环执行乘法

时间:2013-09-29 14:37:46

标签: c++ algorithm loops math multiplication

int x, y; // x is a non-negative integer 
p = 0;
while (x > 0)
{
    if ( x % 2 == 1 )
       p = p + y;
    y = y*2;
    x = x/2;
}
// p == a*b here

我知道这个循环使用代数找到'a'和'b'的乘积:

  

a * b =(1/2)a * 2b

但我不明白代码:

if ( x % 2 == 1 )
    p = p + y;

我希望有人可以解释为什么'p'在x的奇数值上被赋予'p + y'。

6 个答案:

答案 0 :(得分:1)

因为这些是整数,a / 2将是一个整数。如果a为奇数,则该整数已向下舍入,并且在循环的下一次迭代中缺少一半b,即当前迭代中的一整b循环(因为b [y]每次加倍。)

答案 1 :(得分:1)

如果x为奇数,x = x/2将x设置为小于x / 2(因为整数除法将其向下舍入)。需要调整p以允许这样做。

答案 2 :(得分:1)

将乘法视为重复加法,x * y将y加在一起x次。将2 * y加在一起x / 2次也是一样的。从概念上讲,如果x是奇数,它有点不清楚。例如,如果x = 5且y = 3,那么添加2.5倍是什么意思?代码注意到当x是奇数时,加y,然后y = y * 2和x = x / 2。当x为奇数时,这会丢弃.5部分。因此,在此示例中,您添加y一次,然后x变为2(而不是2.5),因为整数除法会丢弃该分数。

在每个循环结束时,您将看到原始x和y的乘积对于p,x和y的当前值等于p + x * y。循环迭代直到x为0,结果完全在p。

如果您创建表并在每次循环时更新它,这也有助于查看发生了什么。这些是每次迭代开始时的值:

x | y  | p
----------
5 | 3  | 0
2 | 6  | 3
1 | 12 | 3
0 | 24 | 15

答案 3 :(得分:1)

while (x > 0) {
    if (x % 2 == 1)
        p = p + y;
    y = y*2;
    x = x/2;
}

想象x = 4,y = 5

迭代:

  1. x是偶数,y = 10,x = 2(即 x可以划分,y应该是一倍
  2. x是偶数,y = 20,x = 1
  3. x是奇数,p = 20,y = 40,x = 0(即 x不能是已分割,y应添加到p
  4. x > 0false,循环结束
  5.   

    p = 4 * y

    现在假设x在开头是奇怪的,让我们说x = 5,y = 2:

    1. x是奇数,p = 2,y = 4,x = 2 (5/2 = 2.5, x的新值将向下舍入,y应在加倍之前添加
    2. x是偶数,y = 8,x = 1
    3. x是奇数,p = 10,y = 16,x = 0
    4.   

      p = y + 4 * y

      首先y是原因,在结果加倍之前将其添加到结果中1 * y)在这种情况下等同于0.5 * (2 * y)

答案 4 :(得分:1)

这可以通过观察(例如)y * 10 = y * 8 + y * 2

来实现

这就像在学校里做纸上乘法一样。例如,要乘以14 x 21,我们一次乘以一个数字(并在需要的地方左移一个数字),所以我们加1x14 + 2 x 14(左移一位)。

    14
  x 21
  ----
    14
   280

在这里,我们做了几乎相同的事情,但是使用二进制而不是十进制。正确的移位与奇数的数字无关,而只是简单地找到数字中的哪些位被设置。

当我们向右移动一个操作数以查找是否设置了一个位时,我们还将另一个操作数向左移动,就像我们在十进制纸上进行算术运算时添加零来移位数字一样。

因此,以二进制方式查看内容时,我们最终得到的结果如下:

      101101
    x  11010
    --------
     1011010
+  101101000
+ 1011010000

如果我们想要,而不是正确地移动操作数,我们可以将掩模向左移动而不是and1重复,我们and与{{} 1}},然后使用1,然后使用2,依此类推(事实上,它可能会更有意义)。然而,无论好坏,在汇编语言中(通常都会执行此类操作),通常更容易移动操作数并使用常量作为掩码,而不是将掩码加载到寄存器中并在需要时将其移位。

答案 5 :(得分:0)

您应该将x重写为2 * b + 1(假设x为奇数)。然后

x*y = (2*b+1)*y = (2*b)*y + y = b*(2*y) + y = (x/2)*(2*y) + y

其中(x / 2)表示整数除法。通过这种方式重写操作,您会看到x / 2,2y和+ y出现。