使用递归计算大数字数的幂

时间:2015-12-10 20:33:00

标签: python recursion exponent

目标是使用递归计算提升到其他大数字的大数字数字,例如,将100位数字提升到另一个100位数字。

我的计划是递归计算exp / 2,其中exp是指数,并根据exp是偶数还是奇数进行额外的计算。

我目前的代码是:

def power(y, x, n):
    #Base Case
    if x == 0:
        return 1

    #If d is even
    if (x%2==0): 
        m = power(y, x//2, n)
        #Print statment only used as check
        print(x, m)
        return m*m

    #If d is odd
    else:
        m = y*power(y, x//2, n)
        #Print statement only used as check
        print(x, m)
        return m*m

我遇到的问题是它进行了太多的计算,而我正在努力弄清楚如何修复它。例如,2 ^ 3返回64,2 ^ 4返回256,2 ^ 5返回1024,依此类推。它计算m * m的次数太多了。

注意:这是解决大数模数的一部分。我正在严格测试代码的指数组件。

2 个答案:

答案 0 :(得分:1)

首先,你的实现有一个奇怪的事情:你使用一个你从未使用的参数n,但只是继续传递而你永远不会修改。

其次第二次递归调用不正确:

else:
    m = y*power(y, x//2, n)
    #Print statement only used as check
    print(x, m)
    return m*m

如果你做数学运算,你会看到你返回:(yy x // 2 2 = y 2 *(x // 2 + 1) (请注意//而不是/),因此太多了 y 。为了正确地执行此操作,您应该将其重写为:

else:
    m = power(y, x//2, n)
    #Print statement only used as check
    print(x, m)
    return y*m*m

(因此从y*部分移除m并将其添加到return语句中,以使其不平方。)

这样做会使您的实现至少在语义上合理。但它无法解决性能/内存问题。

你的comment清楚地表明你想对结果做一个模数,所以这可能是 Project Euler

策略是利用模数在乘法下闭合的事实。换句话说,以下是:

(a b)mod c =((a mod c)*(b mod c))mod c

您可以在程序中使用它来防止生成大数字,从而处理需要很少计算工作量的小数字。

另一个优化是你可以简单地在你的论证中使用square。因此,更快的实现类似于:

def power(y, x, n):
    if x == 0: #base case
        return 1
    elif (x%2==0): #x even 
        return power((y*y)%n,x//2,n)%n
    else: #x odd
        return (y*power((y*y)%n,x//2,n))%n

如果我们使用此函数进行小测试,我们会发现两个结果对于小数字是相同的(可以在合理的时间/内存中处理pow()):(12347**2742)%1009返回{{ 1}}和787L power(12347,2742,1009),因此它们生成相同的结果(当然这不是证明),两者都是等价的,它只是一个简短的结果过滤掉明显错误的测试。

答案 1 :(得分:0)

这是我对这个问题的c版本的处理方法,它适用于正面和负面的曝光:

def power(a,b):
  """this function will raise a to the power b but recursivelly"""
  #first of all we need to verify the input
  if isinstance(a,(int,float)) and isinstance(b,int):
    if a==0:
      #to gain time
      return 0
    if b==0:
        return 1
    if b >0:
      if (b%2==0): 
      #this will reduce time by 2 when number are even and it just calculate the power of one part and then multiply 
        if b==2:
          return a*a
        else:
          return power(power(a,b/2),2)
      else:
      #the main case when the number is odd
        return a * power(a, b- 1)
    elif not b >0:
      #this is for negatives exposents
      return 1./float(power(a,-b))
  else:
    raise TypeError('Argument must be interfer or float')