16B. Example: Computing Powers

Let's look at the problem of computing xk (x to the k-th power) where x is a real number and k is a positive integer. Breaking this down into cases yields a simple case and a slightly more complicated case.

  1. If k = 1 then xk = x.

  2. If k > 1 then it is clear that xk = x·xk−1. We can use our function to compute xk−1.

That leads to the following definition of power(x, k).

  // power(x,k) returns x to the k-th power.
  //
  // Requirement: k > 0.

  double power(double x, int k)
  {
    if(k == 1)
    {
      return x;
    }
    else 
    {
      return x * power(x, k-1);
    }
  }
That works, but we can do better. Imagine computing x8. Our algorithm does it as follows.
  x8 = x · x7
     = x · x · x6
     = x · x · x · x5
     = x · x · x · x · x4
     = x · x · x · x · x · x3
     = x · x · x · x · x · x · x2
     = x · x · x · x · x · x · x · x1
     = x · x · x · x · x · x · x · x
It ends up doing 7 multiplications. But we can compute x8 more efficiently as follows.
  x8 = (x4)·(x4)
  x4 = (x2)·(x2)
  x2 = (x1)·(x1)
The advantage is that each right-hand side consists of a value multiplied by itself. We only need to compute that value once, and we end up computing x8 using only 3 multiplications. The same idea allows us to compute x1024 using only 10 multiplications.

So we use the rule:

  1. If k is even then xk = (xk/2)2

(We need k to be even to ensure that k/2 is an integer.) Here is the improved function definition.

  // power(x,k) returns x to the k-th power.
  //
  // Requirement: k > 0.

  double power(double x, int k)
  {
    if(k == 1)
    {
      return x;
    }
    else if(k % 2 == 0)
    {
      double p = power(x, k/2);
      return p*p;
    }
    else 
    {
      return x * power(x, k-1);
    }
  }
That is a much more efficient algorithm than the previous algorithm. For example, to compute x9, it uses the rule
  x9 = x · x8
then it uses the efficient algorithm for x8 shown above. To compute x18, it uses
  x18 = x9 · x9
and we have seen that x9 is computed efficiently. In fact, the new function computes xn using no more that 2log2(n) multiplications.

Exercises

  1. Suppose the power function is written as follows. Does it work?

      // power(x,k) returns x to the k-th power.
      //
      // Requirement: k > 0.
    
      double power(double x, int k)
      {
        if(k == 1)
        {
          return x;
        }
        else if(k % 2 == 0)
        {
          return power(x*x, k/2);
        }
        else 
        {
          return x * power(x, k-1);
        }
      }
    
    Answer