Using recursion to calculate powers of large digit numbers

天涯浪子 提交于 2019-12-08 12:33:23

问题


The goal is to calculate large digit numbers raised to other large digit numbers, e.g., 100 digit number raised to another 100 digit number, using recursion.

My plan was to recursively calculate exp/2, where exp is the exponent, and making an additional calculation depending on if exp is even or odd.

My current code is:

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

The problem I run into is that it makes one too many calculations, and I'm struggling to figure out how to fix it. For example, 2^3 returns 64, 2^4 returns 256, 2^5 returns 1024 and so on. It's calculating the m*m one too many times.

Note: this is part of solving modulus of large numbers. I'm strictly testing the exponent component of my code.


回答1:


First of all there is a weird thing with your implementation: you use a parameter n that you never use, but simply keep passing and you never modify.

Secondly the second recursive call is incorrect:

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

If you do the math, you will see that you return: (y yx//2)2=y2*(x//2+1) (mind the // instead of /) which is thus one y too much. In order to do this correctly, you should thus rewrite it as:

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

(so removing the y* from the m part and add it to the return statement, such that it is not squared).

Doing this will make your implementation at least semantically sound. But it will not solve the performance/memory aspect.

Your comment makes it clear that you want to do a modulo on the result, so this is probably Project Euler?

The strategy is to make use of the fact that modulo is closed under multiplication. In other words the following holds:

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

You can use this in your program to prevent generating huge numbers and thus work with small numbers that require little computational effort to run.

Another optimization is that you can simply use the square in your argument. So a faster implementation is something like:

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

If we do a small test with this function, we see that the two results are identical for small numbers (where the pow() can be processed in reasonable time/memory): (12347**2742)%1009 returns 787L and power(12347,2742,1009) 787, so they generate the same result (of course this is no proof), that both are equivalent, it's just a short test that filters out obvious mistakes.




回答2:


here is my approach accornding to the c version of this problem it works with both positives and negatives exposents:

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')


来源:https://stackoverflow.com/questions/34211198/using-recursion-to-calculate-powers-of-large-digit-numbers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!