我跟随此http://www.cs.berkeley.edu/~vazirani/algorithms/chap1.pdf(第24页底部)。在书中,作者描述了Al Khwarizmi乘法算法。这是我的实现
static int RecMultiply(int x, int y)
{
if (y == 0)
return 0;
int z = RecMultiply(x, y / 2);
if (y % 2 == 0)
return 2 * z;
else
return x + 2 * z;
}
我已经完成了几次代码,我只是没有理解它。为什么底部将x添加到2 * z?在我看来,z既可用作跑步总数,也可用作"右列"书中算法中的数字。有人可以打破这段代码并解释一下吗?
答案 0 :(得分:3)
这很简单。
Z是通过乘以x和y的一半来计算的。
如果y是偶数奇偶校验(如果是部分)则返回2 * z = 2 * x * y / 2 = x * y(这是原始请求)
如果y是奇数奇偶校验(否则为部分),则返回2 * z + x。我们为什么要加x?那是因为y / 2对于偶数和跟随奇数是相同的。所以Z会是一样的。但是,如果这个if部分我们检测它是奇数还是偶数,如果是奇数,我们再次将x加到结果中。
答案 1 :(得分:3)
由于乘法是简单的重复加法,如果y
是对,则可以将其除以2,并将x
乘以2。 (所以,2 * 2 = 2 + 2.2 * 3 = 2 + 2 + 2,2 * 4 = 2 + 2 + 2 + 2 ....)
如果y
为奇数,则可以减去1,得到一对y
,并且需要添加x
,(基本上是1 * y)。
这是一个细分:
RecMultiply(5,5) :
+- z = RecMultiply(5,2)
| return 5 + 2 * z (=20 +5 =25)
|
|
+-- RecMultiply(5,2) :
+- z = RecMultiply(5,1)
| return 2 * z (=10)
|
+-- RecMultiply(5,1) :
+- z = RecMultiply(5,0)
| return 5 + 0
|
+---RecMultiply(5,0) :
return 0
RecMultiply(5,4) :
+- z = RecMultiply(5,2)
| return 2 * z (=)
|
+-- RecMultiply(5,2) :
+- z = RecMultiply(5,1)
| return 2 * z (=10)
|
+-- RecMultiply(5,1) :
+- z = RecMultiply(5,0)
| return 5 + 0
|
+---RecMultiply(5,0) :
return 0
所以,基本上,在递归位(负责所有对乘法)之后,您可能需要添加另一个y
,在上面的第一种情况下,对于第一个5
呼叫)。
请注意y=1
的特殊情况,这意味着x*1
在我们的案例中显然是5
。同样的逻辑适用。
如果有帮助,您可能希望这样看:
static int RecMultiply(int x, int y)
{
switch (y)
{
case 0:
return 0;
break;
case 1:
return x;
break;
default:
return (y%2 ==0) ? RecMultiply(x, y/2)
: x + RecMultiply(x, y/2);
break;
}
}
我认为它以更容易理解的方式表示+1(或奇数情况)。