tags:

views:

4701

answers:

12

What is the most efficient way given to raise an integer to the power of another integer in C?

// 2^3
pow(2,3) == 8

// 5^5
pow(5,5) == 3125
A: 

As I recall, math.h contains a pow(x, y) function

R. Bemrose
yeah but this one works with doubles
Drealmer
A: 

Ignoring the special case of 2 raised to a power, the most efficient way is going to be simple iteration.

int pow(int base, int pow) {
  int res = 1;
  for(int i=pow; i<pow; i++)
    res *= base;

  return res;
}

EDIT: As has been pointed out this is not the most efficient way... so long as you define efficiency as cpu cycles which I guess is fair enough.

O(N) where O(log N) is possible - see yarrkov
MSalters
This could actually be the most efficient. N can't be arbitrarily large. Its maximum is either 31 or 63 (depending on your int size). Its like how insertion sort beats quicksort for low N.
paperhorse
This code doesn't work as written, i should be initialized to 0 not pow. @paperhorse, N is pow, ie 0 to INT_MAX.
Greg Rogers
+2  A: 

An extremly specialized case is, when you need say 2^(-x to y), where x, is of course is negative and y is too large to do shifting on an int. You can still do 2^x in constant time by screwing with a float.

struct IeeeFloat
{

    unsigned int base : 23;
    unsigned int exponent : 8;
    unsigned int signBit : 1;
};


union IeeeFloatUnion
{
    IeeeFloat brokenOut;
    float f;
};

inline float twoToThe(char exponent)
{
    // notice how the range checking is already done on the exponent var 
    static IeeeFloatUnion u;
    u.f = 2.0;
    // Change the exponent part of the float
    u.brokenOut.exponent += (exponent - 1);
    return (u.f);
}

You can get more powers of 2 by using a double as the base type. (Thanks a lot to commenters for helping to square this post away).

There's also the possibility that learning more about Ieee floats, other special cases of exponentiation might present themselves.

Doug T.
Nifty solution, but unsigend??
paxdiablo
Yeah, my bad. :) thanks for pointing it out.
Doug T.
Nice solution if it's what you want, but this doesn't perform exponentiation in the number field of the int, so behaves differently on overflow from repeated multiplication (which is the definition of exponentiation after all).
Steve Jessop
An IEEE float is base x 2 ^ exp, changing the exponent value won't lead to anything else than a multiplication by a power of two, and chances are high it will denormalize the float ... your solution is wrong IMHO
Drealmer
I think he means *= rather than +=. Good spot, I missed that.
Steve Jessop
*= won't work either, exponent can be null
Drealmer
I take that back, I'm talking total nonsense. As is this solution.
Steve Jessop
You are all correct, I misremembered that my solution was originally written, oh so long ago, for powers of 2 explicitly. I've rewritten my answer to be a special case solution to the problem.
Doug T.
Firstly, the code is broken as quoted, and requires editing to get it to compile. Secondly the code is broken on a core2d using gcc. see [this dump](http://pastebin.com/m70045534)Perhaps I did something wrong. I however do not think this will work, since the IEEE float exponent is base 10.
freespace
Base 10? Uh no, it's base 2, unless you meant 10 in binary :)
Drealmer
Doesn't seem to work for powers of 2 either... I would like to see this in action, can some one spot my mistake in my previous pastebin?Also, embrassingly, I made an error in my previous comment, and said base 10 when I _really_ wanted base 2 ;)
freespace
You still should be multiplying the exponents, not adding them. And look into CPU-specific implementations. For instance on x86, bsr to find the hibit will be no slower than an int->double conversion and probably faster.
Steve Jessop
Just noticed that you're now calculating pow(2,n). This can be done in a single CPU instruction on most platforms with 1 << n, except that you must range-check n first, since 1 << 32 is undefined behaviour.
Steve Jessop
Thanks for humbling me, seriously. I completely misremembered something I did long ago, and was corrected. Thank god too, because someone might have tried to run with my solution! If you voted me up, feel completely free to undo it
Doug T.
-1 useless; exponentiating 2 is more easily performed by bitshifting. Also bitfields have unspecified order within the larger type so this code is not portable even across compilers with the same (IEEE) float implementation. Further, you need `signed char` if you claim your comment is correct, as the signedness of char is unspecified.
R..
+10  A: 

Exponentiation by squaring might be worth taking a look at.

ddvlad
+50  A: 

Exponentiation by squaring.

int ipow(int base, int exp)
{
    int result = 1;
    while (exp)
    {
        if (exp & 1)
            result *= base;
        exp >>= 1;
        base *= base;
    }

    return result;
}

This is the standard method for doing modular exponentiation for huge numbers in asymmetric cryptography.

Elias Yarrkov
With maybe break-out special cases for small exponents known to have better algorithms: turns out the questioner doesn't expect overflow anyway, so these are presumably common.
Steve Jessop
AKA the "fast exponentiation algorithm".
wnoise
Thanks for the code Elias. I beautified the code a bit for better presentation.
Ashwin
"res *= base;" should be "result *= base;"
Jeff Moser
You should probably add a check that "exp" isn't negative. Currently, this function will either give a wrong answer or loop forever. (Depending on whether >>= on a signed int does zero-padding or sign-extension - C compilers are allowed to pick either behaviour).
user9876
GSL's gsl_sf_pow_int implements this, including the negative case handling: http://www.gnu.org/software/gsl/manual/html_node/Power-Function.html
Rhys Ulerich
A: 
int pow( int base, int exponent)
{
    if (exponent == 0) return 1;  // base case;
    int temp = pow(base, exponent/2);
    if (exponent % 2 == 1) return temp * temp;
    else return (base * temp * temp);
}
chris
+6  A: 

Note that exponentiation by squaring is not the most optimal method. It is probably the best you can do as a general method that works for all exponent values, but for a specific exponent value there are might be a better method.

For instance, if you want to x^15, the method of exponentiation will give you:

x^15 = (x^7)*(x^7)*x 
x^7 = (x^3)*(x^3)*x 
x^3 = x*x*x

This is a total of 6 multiplications.

It turns this can be done using "just" 5 multiplications.

n*n = n^2
n^2*n = n^3
n^3*n^3 = n^6
n^6*n^6 = n^12
n^12*n^3 = n^15

I don't remember the source now, but I vaguely remember that there are no efficient algorithms to find this optimal sequence of multiplications.

Pramod
Yes there is, binary exponentiation.
Jeremybub
+1  A: 

When you say "efficiency," you need to specify efficient in relation to what. Speed? Memory usage? Code size? Maintainability?

Andy Lester
Marked up (back to zero) because this answer is not /unhelpful/, but could be insightful to some.
Arafangion
Indeed. You cannot optimize "efficiency" without knowing what sort of efficiency you're interested in. All optimizations are tradeoffs.
Andy Lester
+3  A: 

There is an exhaustive discussion of this topic in:

D.E. Knuth, The Art of Computer Programming, Vol. 2: Seminumerical Algorithms, 2nd ed. Addison-Wesley, Reading, MA, 1981.

In terms of the number of multiplications required, there is an algorithm there that is superior to repeated squaring, but what the most optimal method will be depends on your exact application.

PeterAllenWebb
+2  A: 

Just as a follow up to comments on the efficiency of exponentiation by squaring.

The advantage of that approach is that it runs in log(n) time. For example, if you were going to calculate something huge, such as x^1048575 (2^20 - 1), you only have to go thru the loop 20 times, not 1 million+ using the naive approach.

Also, in terms of code complexity, it is simpler than trying to find the most optimal sequence of multiplications, a la Pramod's suggestion.

Edit:

I guess I should clarify before someone tags me for the potential for overflow. This approach assumes that you have some sort of hugeint library.

Jason Z
A: 

There are a few decent answers above, such as the one by PeterAllenWebb (citing Knuth) and the one by Pramod (the terminology he was missing though was "addition chains").

Exponentiation by Squaring is indeed not optimal. Here is one very clever method:

"Fast Exponentiation Using Data Compression" by Yacov Yacobi, SIAM Journal on Computing, Volume 28 , Issue 2 (April 1999), Pages: 700 - 703 .

It would be nice if you could show the actual algorithm
Nathan Fellman
A: 

I am working on an efficent algorithm here...

Now, I don't know if this would be computationally expensive...

I was look on the lines that 3^4 = 81... instead of iterating 4 times or recursive calling the function 4 times we know that 3*3 = 9 and 9^2 = 81. This gives us the approach to say that 3^4 = 9^2 going through the iterations 2 times is much more efficent then 4, but how and where in the function could we determine this without too much overhead?

skilz80