Recursion pow(x,n)的递归方法,用于查找小于10次乘法的2^(37)

Recursion pow(x,n)的递归方法,用于查找小于10次乘法的2^(37),recursion,Recursion,pow(x,n)的正则递归方法如下: 功率(x,n): 使用这种方法,2^(37)将需要37次乘法。我如何修改它以将乘法数减少到10以下?我认为只有在功能不过度的情况下才能做到这一点 您可以用对数时间而不是线性时间计算数字的幂 int cnt = 0; // calculate a^b int pow(int a, int b){ if(b==0) return 1; if(b%2==0){ int v = pow(a, b/2); cnt +=

pow(x,n)的正则递归方法如下:

功率(x,n):


使用这种方法,2^(37)将需要37次乘法。我如何修改它以将乘法数减少到10以下?我认为只有在功能不过度的情况下才能做到这一点

您可以用对数时间而不是线性时间计算数字的幂

int cnt = 0;

// calculate a^b
int pow(int a, int b){
    if(b==0) return 1;
    if(b%2==0){
        int v = pow(a, b/2);
        cnt += 1;
        return v*v;
    }else{
        int v = pow(a, b/2);
        cnt += 2;
        return v*v*a;        
    }
}

通过程序验证,上述代码的乘法数将为9。

与invin做的稍有不同,我得到了8个乘法。这是一个Ruby实现。请注意,Ruby方法返回最后计算的表达式的结果。有了这样的理解,它读起来非常像伪代码,但实际上您可以运行它:

$count = 0

def pow(a, b)
  if b > 0
    $count += 1    # note only one multiplication in both of the following cases
    if b.even?
      x = pow(a, b/2)
      x * x
    else
      a * pow(a, b-1)
    end
  else             # no multiplication for the base case
    1
  end
end

p pow(2, 37)       # 137438953472
p $count           # 8
请注意,调用该方法的幂的顺序是

37 -> 36 -> 18 -> 9 -> 8 -> 4 -> 2 -> 1 -> 0
每个箭头代表一次乘法。计算零次方总是得到1,没有乘法,并且有8个箭头

由于n的偶数值为xn=(xn/2)2=(x2)n/2,因此我们可以推导出这种细微不同的实现:

$count = 0

def pow(a, b)
  if b > 1
    if b.even?
      $count += 1
      pow(a * a, b/2)
    else
      $count += 2
      a * pow(a * a, b/2)
    end
  elsif b > 0
    a
  else
    1
  end
end

p pow(2, 37)       # 137438953472
p $count           # 7

这个版本包含了原始问题中的所有基本情况,很容易运行并确认它在7次乘法中计算2^37,并且不需要任何局部变量分配。当然,对于生产使用,您可以注释掉或删除对
$count

的引用。使用这种方法,您只需7次乘法即可计算2^(37)

功率(x,n):

现在让我们用这种方法计算2^(37)——

2^(37)=


此函数不是过多的,因此它在计算后重用值。因此,计算2^(37)只需要7次乘法。

注意,当n为偶数时,xn=(xn/2)**2,或当n为奇数时,乘以x。这是正确的递归调用次数,因为
b
上的算术是正确的,但是,当尝试使用大于30的功率时,实际功率计算溢出了Java
int
。您是否在n个偶数/奇数行上调用了
pow
函数两次?@pjs是的,使用了递归。那么,如果您声明以7次乘法计算结果,您就错了。通过在每一级别将递归调用的数量增加一倍,就可以取消将指数减半的工作。如果你不相信它的逻辑,那么试着实现它并计算。您会发现当前的算法实际上执行36次乘法。
$count = 0

def pow(a, b)
  if b > 1
    if b.even?
      $count += 1
      pow(a * a, b/2)
    else
      $count += 2
      a * pow(a * a, b/2)
    end
  elsif b > 0
    a
  else
    1
  end
end

p pow(2, 37)       # 137438953472
p $count           # 7
    = 1 ... n=0

    = 0 ... x=0

    = x ... n=1

    = pow(x,n/2) * pow (x,n/2) ... n = even

    = x * pow(x,n/2) * pow(x,n.2) ... n = odd
     = 2 * 2^(18) * 2^(18)

     =              2^(9) * 2^(9)

     =                      2 * 2^(4) * 2^(4)

     =                                  2^(2) * 2^(2)

     =                                          2 * 2