views:

456

answers:

7

So given x, and power, n, solve for X^n. There's the easy way that's O(n)... I can get it down to O(n/2), by doing

numSquares = n/2;
numOnes = n%2;
return (numSquares * x * x + numOnes * x);

Now there's a O(log(n)) solution, does anyone know how to do it? It can be done recursively.

+1  A: 

The standard trick is to generate the powers of x in sequence x2, x4, x8, x16, x32, ... and include those that are needed in the result.

Jonathan Leffler
unless i'm not getting your answer, you can't do this infinitely though right?
Mike
@Mike: You can only do anything infinitely if you have an infinite computer, and most of us are stuck with ordinary, very finite computers. If you use a multi-precision arithmetic package, you can work with numbers big enough that they'll blow your brains out.
Jonathan Leffler
Mike: Why do you need to do it infinitely? You only have to do it up to `n`.
Gabe
@gabe that's true. nevertheless, i think Poita_ provided the best answer.
Mike
+1: Here is an example to illustrate this answer. Assume we have to compute x^26. Now, 26 = 11010 in binary. The '1' positions signify 16, 8, and 2. So, x^26 = (x^16) * (x^8) * (x^2). Now, if have the series x, x^2, x^4, x^8, x^16 computed, then we can pick selected items of the series and multiple them. Summary: To compute x^n, convert n to binary, find the bit positions (always 2's power) that are 1, compute them starting from the lower side, and multiply the suitable ones.
ArunSaha
A: 

x^n = e^(n*ln x), if i get you right?

vittore
You've produce a solution that's O(1) and requires floating-point operations. He's looking for an integer-only solution that's O(lg n).
Gabe
His solution is certainly not O(1), unless you have have a constant time algorithm for e^(x), which would be great news.
Jacob Schlather
but it is O(1). Increasing x doesn't increase the time to evaluate e^x.
Jason S
Most likely for a wide variety of numbers the constant is higher than the entire non-constant time for integer only algorithms.
Mark B
@Marck B: really doubt this to be frank, exp implemented at very low level
vittore
+15  A: 
sth
+1. Nice selective hint.
pst
+14  A: 

Well, you know that xa+b = xa xb so...

int pow(int x, unsigned int y)
{
  if (y == 0) return 1;
  if (y == 1) return x;
  int a = y / 2;
  int xa = pow(x, a);
  if (a + a == y) // y even
    return xa * xa;
  else
    return xa * xa * x;
}
Peter Alexander
you also need a `if (y<0) { return (x==1)?1:0; }` and to throw an exception for `y<0, x==0`
Inverse
Recursion for something already so computationally expensive as calculating the power of a number seems a tad bit overkill
susmits
What's overkill about recursion exactly? Also, it's not computationally expensive, it has O(lg(n)) run time.
Peter Alexander
I should have said computationally intensive, sorry about that. The function isn't tail-call optimizable, and I have a suspicion the function call overhead here would be comparable to the execution time of each call.
susmits
If he wants to make micro-optimisations then that's up to him. I'm presenting something that is elegant so as to demonstrate the concept. Recursive solutions are almost always easier to understand that iterative ones.
Peter Alexander
-1 for writing out the solution to an obvious homework problem...
BlueRaja - Danny Pflughoeft
+2  A: 

You'll find an explanation here: Fast exponentiation. For some values of n, you can calculate x^n with fewer multiplications than by using the powers of two trick.

John D. Cook
+7  A: 

The usual implementation is something along these lines (cribbed from the wikipedia article):

long power(long x, unsigned long n)
{
    long result = 1;
    while (n > 0) {
        /* n is odd, bitwise test */ 
        if (n & 1) {
            result *= x;
        }
        x *= x;
        n /= 2;     /* integer division, rounds down */
    }
    return result;
}

Recursion isn't necessary or (I'd say) particularly desirable, although it can win on obviousness:

long power(long x, unsigned long n)
{
    if (n == 0) return 1;
    long result = power(x, n/2); // x ^ (n/2)
    result *= result;            // x ^ (n/2)*2
    if (n & 1) result *= x;      // x ^ n
    return result;
}

Of course in any version you overflow a long pretty quickly. You can apply the same algorithms to your favourite bigint representation, although any bigint library is going to include an integer power function already.

Both versions of the function above return 1 for power(0,0). You may or may not consider this a bug.

Steve Jessop
How can we mark answers as Community Wikipedia?
Windows programmer
Fun fact: g77 uses exponentiation by squaring to calculate integral powers.
susmits
A: 

The answer above using exp and log requires 2 long PF power series evaluations, which is usually vastly slower the lg(n) method.

Raoul Ohio