请解释一下这个程序背后的逻辑,它使用递归来计算a ^ b(一个上升到幂b)

时间:2013-04-03 06:19:25

标签: c

真的很尴尬!!我只是不理解下面的小程序的工作,它使用递归来计算数字“a”(“a”上升到幂“b”)的幂。请解释逻辑在这个函数后面使用。我不明白使用“x * x”参数,n / 2参数和“n modulo 2”部分。请为我解剖。

    #include<stdio.h>

    int foo(int,int);

    int main() {
      int a,b;

      printf("Enter number a and its power b\n");
      scanf("%d%d",&a,&b);

      printf("a raised to b is %d", foo(a,b));
      return 0;
    }


    int foo ( int x , int n) {
      int val=1;

      if(n>0) {
        if (n%2 == 1) 
          val = val *x;
        val = val * foo(x*x , n/2);
      }

      return val;
    }

3 个答案:

答案 0 :(得分:6)

这种递归背后的想法是, b =(a 2 b / 2 b < / sup> = a(a 2 (b-1)/ 2

根据b是奇数还是偶数(即n%2 == 1部分),您可以选择其中一个公式来确保b / 2或(b-1)/ 2仍然是整数。请注意,对于奇数n,代码中的n/2实际上是(n-1)/ 2,因为整数除法会自动向下舍入。

此递归终止,因为指数随着每一步逐渐变小。

答案 1 :(得分:4)

这利用了x^23等权力可以改写为x^16 * x^4 * x^2 * x^1

的事实

现在计算x^16非常简单,因为它只是(((x^2)^2)^2)^2,只有4次乘法而不是计算x * x * x * ... 16 times ... * x

现在请注意,在计算x^16时,您还需要运行x^4x^2来计算您的号码。所以最后,你只用了7次乘法而不是22次计算x^23

现在n % 2n / 2进入图片的位置是判断2的幂是否在n中(在我们的例子中,在23的二进制表示中是8?no)。

所以你只需要遍历n的位。你每次都是x,如果你正在查看当前n位中的1,你将平方数乘以你的结果。

更新

以这种方式编写数字的技巧是以二进制形式查看n。 23是10111 2 ,或者我们可以写出地方值23 = 1*16 + 0*8 + 1*4 + 1*2 + 1*1

这意味着x^23 = x^(16 + 4 + 2 + 1)并且由于指数法则,= x^16 * x^4 * x^2 * x^1这就是我们开始的目标。

另一个简单示例:取x^44。我们用二进制写为101100 2 ,所以我们可以说

44  =  1*32 + 0*16 + 1*8 + 1*4 + 0*2 + 0*1  =  32 + 8 + 4

所以

x^44 = x^(32 + 8 + 4) = x^32 * x^8 * x^4

然后我们计算以下

1:   x^2  = (x)^2                     (from the x we are given)
2:   x^4  = (x^2)^2                   (x^2 from step 1)
3:   x^8  = (x^4)^2                   (x^4 from step 2)
4:   x^16 = (x^8)^2                   (x^8 from step 3)
5:   x^32 = (x^16)^2                  (x^16 from step 4)
6:   x^44 = (x^32) * (x^8) * (x^4)    (using results of steps 2, 3, and 5)

答案 2 :(得分:1)

如你所说,foo递归地工作。你为什么不一步一步地完成它?假设您a==2b==3

第一步

int foo ( int x , int n) // x == 2, n==3
{
int val=1;

if(n>0) // n == 3, true!
{
    if (n%2 == 1) //true!
    val = val *x; // val = 1 * 2;
    val = val * foo(x*x , n/2); // next step
}

return val;
}

第二步

int foo ( int x , int n) // x == 4, n==1
{
int val=1;

if(n>0) // n == 1, true!
{
    if (n%2 == 1) //true
    val = val *x; val = 1 * 4;
    val = val * foo(x*x , n/2); // next step -> 4 * ...
}

return val;
}

在第二步中,返回4,在第一步中产生

val = val * foo(x*x , n/2); // 2 * 4 in the first step and this equals 8