emschorsch
emschorsch

Reputation: 1669

Efficiency of recursion vs. iteration for exponents

So I'm trying to implement a more efficient method of calculating 2^n.

I know that you can split it up so that it is O(logn) and it is easy to do using recursion. You keep dividing by 2 and multiply it by the lower power when its odd (or something like that). The problem is I wrote out my multiplication method by hand since its for big numbers. So it needs to return more than one parameter.

One solution I can think of is to make a pair which contains all the needed information. Other than that though I was trying to figure out how to write it using iteration. The only way I can see of doing is using some kind of data structure and then loop through dividing n by 2 and storing the value when n is odd. Then write a for loop and check at each iteration if the value is contained in the data structure. This seems to me like a relatively costly operation.

Is it possible that it would end up less efficient than the recursive version?

I'm doing this because:

  1. I can't get gnp working.
  2. I think I am learning from writing the big numbers class and working with it.

Upvotes: 1

Views: 3400

Answers (2)

Philippe
Philippe

Reputation: 9762

If you're going to work with big numbers, rather than reinventing the wheel, you probably should take a look at the GNU MP Bignum Library.

Regarding the recursion versus iteration question, the answer is that you can always write them to be equivalent; a recursive function that only calls itself as a tail call is as efficient as a while loop (provided that your compiler supports tail call optimization, but the most common compilers do). For instance, the tail-recursive version of the fast exponentiation function you are describing is (in pseudo-code):

function fastExp(base, exponent, accumulator) {
  if(exponent == 0) {
    return accumulator;
  } else if(exponent % 2 == 0) {
    return fastExp(base * base, exponent/2, accumulator);
  } else {
    return fastExp(base, exponent-1, base * accumulator); 
  }
}

Think of this recursive function as a loop, where the looping condition is exponent != 0, and the recursive calls are like gotos to the beginning of the loop. (You need to call it with accumulator = 1 when you start, by the way.) It is equivalent to the following:

function fastExp(base, exponent) {
  var accumulator = 1;
  while(exponent != 0) {
    if(exponent % 2 == 0) {
      base *= base;
      exponent /= 2;
    } else {
      exponent -= 1;
      accumulator *= base;
    }
  }
  return accumulator;
}

So you can see that they are equivalent, and therefore will perform the same number of operations.

Upvotes: 6

parapura rajkumar
parapura rajkumar

Reputation: 24423

If you are storing everything as a sequence of 1 s and 0 s..i.e.. in Binary format, 2^n is simply a sequence of 0 s preceded by a single 1 , maybe you can use fact to simply your code

2^1 = 10
2^2 = 100
2^3 = 1000
2^4 = 10000

so on and so forth, Unless this is a learning exercise I would go with a standard arbitrary precision library like what Philippe suggested

Upvotes: 0

Related Questions