views:

1179

answers:

8

Hi!

I need to get the result from pow(a,b) as an integer (both a and b are integers too). currently the calculations where (int) pow( (double)a, (double)b) is included are wrong. Maybe someone can help with a function that does the pow(a,b) with integers and returns an integer too?

But here is the odd part: I made my script in Linux with Geany (and g++/gcc compiler) and had just pow(a,b) the script compiled and worked fine. But in university I have Dev-C++ (and MS Windows). In Dev-C++ the script didn't compile with an error [Warning] converting to int' from double'

I need to make this scrpit work under Windows (and Mingw compiler) too.

Thanks in advance,

-skazhy

+4  A: 

I assume your homework assignment is to write an integral exponent function. First, take a look at what an exponent is:

http://en.wikipedia.org/wiki/Exponent

Then, look in your textbook for how to multiply numbers in C. You'll want to use a for loop.

John Millikin
+1 - Nice suggestion about the for loop.
James Black
A for loop is the last thing you want to use because of its linear complexity, so I suppose this is a joke at the expense of our student ?
Matthieu M.
@Matthieu: I doubt a student struggling with multiplication will be able to build a logarithmic exponentiation function. Even if somebody wrote one as an answer for him to copy-paste, it would be obvious to the instructor that he didn't write it himself.
John Millikin
And now that is exactly what happened.
notJim
+3  A: 

A nice recursive approach you can show off:

int myPow(int x, int p) {
  if (p == 0) return 1;
  if (p == 1) return x;
  return x * myPow(x, p-1);
}
Zed
Linear complexity, dunno if it is worse than the for loop or not :x
Matthieu M.
Cool, I had no idea the answer to 4^(-2) was "Maximum recursion depth exceeded" (I'm just kidding :p, but it's not hard to add the negative case also)
Falaina
It is worse because it has the same behavior as a for loop plus the function call overhead.
Jodi
@Jodi: You assume the compiler does not inline expand the function. Also it looks so cool like that.
Martin York
@Falaina: whatever the answer to 4^(-2) is, it's not an integer, so negative exponents are not valid inputs. Next you'll be expecting `operator/` to give a sensible answer with operand 0...
Steve Jessop
@Martin York: a fair assumption, functions with function calls or loops are generally not inlined by g++, for instance.
Bill
If you're going to show off with a nifty recursive implementation, at least make it use the O(log(N)) algorithm, and make it tail recursive.
Stephen Canon
YAGNI. Not for a week 1 homework assignment, anyway. Extreme programming says, write the first thing that works ;-)
Steve Jessop
@Martin York, @Bill: could the compiler even inline this if it wanted to? It's non-tail recursive call where the depth of recursion is unknown at compile time.
csj
@csj: it's easy enough for the compiler to do a continuation-passing-style transform on it, and then tail-call optimization.
Novelocrat
+1  A: 

Instead of casting the double to an int in the (int) pow((double)a, (double)b) line, try rounding the results of pow, and then cast to int if necessary.

It's probably one of those floating point problem when you truncate, especially if your result's off by one.

Calyth
+12  A: 

A better recursive approach than Zed's, don't know why you failed so closed Zed :x

int myPow(int x, int p)
{
  if (p == 0) return 1;
  if (p == 1) return x;

  int tmp = myPow(x, p/2);
  if (p%2 == 0) return tmp * tmp;
  else return x * tmp * tmp;
}

Much better complexity there O(log²(p)) instead of O(p). I should add that this really is a classic...

Matthieu M.
Does it cope with negative p?
Martin York
That's a so typical premature optimization...
Zed
@Martin: of course not, it's Savagely Optimized™
John Millikin
Of course you could extend it to if (p == 2) return x * x; if (p == 3) return x * x * x; ... up to 2^32
Zed
+1 for the squaring approach (and I disagree that that's a premature optimization!) But perhaps the return type ought to be "long", to be able to handle larger exponents without overflowing (on platforms where sizeof long > sizeof int).
Jim Lewis
Choosing the correct algorithm is never a premature optimization, especially when the algorithm is (a) so simple and (b) printed in Knuth. There is no excuse for not knowing and using this particular algorithm.
Stephen Canon
What, there's no excuse for turning in your first ever programming assignment without having read Knuth? Not sure what the point of doing the course is, if you can already code :-)
Steve Jessop
@Zed - don't be silly - that should be a switch statement ;-)
Steve314
@Martin York: no obviously not, negative powers lead to square roots which are typically not integers. @Jim Lewis: the request was for the return type to be an int.
Matthieu M.
@Mattieu: negative powers are reciprocals, which are integers only in one case: 1^-1 etc.
Steve Jessop
A: 

C++ standard doesn't have int pow(int, int) (It has double pow(double, int), float ...). Microsoft's cmath uses C math.h that has not ipow. Some cmath headers define template version of pow.

$ cat main.cpp
#include <cmath>

int main() {
  std::pow(2,2);
}

$ gcc main.cpp # this cmath has template pow
...snip... std::pow<int, int>(int, int)]+0x16): undefined reference to `pow'
collect2: ld returned 1 exit status
1 ;( user@host:
$ gcc main.cpp -lm

Search for function:ipow lang:c++ on Google Code .

Here's example from the first link:

template <typename Type1, typename Type2>
Type1 ipow(Type1 a, Type2 ex)
// Return a**ex
{
    if ( 0==ex )  return 1;
    else
    {
        Type1 z = a;
        Type1 y = 1;
        while ( 1 )
        {
            if ( ex & 1 )  y *= z;
            ex /= 2;
            if ( 0==ex )  break;
            z *= z;
        }
        return y;
    }
}

See calculating integer powers (squares, cubes, etc.) in C++ code.

J.F. Sebastian
+2  A: 

Or you could use a litte bit of template metaprogramming :)

template<int X, int P>
struct Pow
{
    enum { result = X*Pow<X,P-1>::result };
};
template<int X>
struct Pow<X,0>
{
    enum { result = 1 };
};
template<int X>
struct Pow<X,1>
{
    enum { result = X };
};

int main()
{
    std::cout << "pow(3,7) is " << Pow<3,7>::result << std::endl;
    return 0;   
}

This code has the best complexity, O(1), because the evaluation will happen at compile time. Of course this will only work with integer values. However, this function is is only provided for completeness (and fun).

fmuecke
I also must admit, that this will not work with older c++ compilers...
fmuecke
But its still pretty awesome solution :)
Nick Bedford
+1  A: 

Wouldn't a tail-recursive function be best? Something like:

int myPow_helper(int x, int p, int result) {
   if (p == 0) {
      return result;
   } else {
      return myPow_helper(x, p-1, result*x);
   }
}

int myPow(int x, int p) {
   return myPow_helper(x, p, 1);
}
blcArmadillo
+1  A: 

Mostly in reply to Zeds simple recursion...

Why is recursion assumed better than iteration? Especially in C++. What's wrong with...

int myPow(int x, int p) {
  int i = 1;
  for (int j = 1; j < p; j++)  i *= x;
  return i;
}

I'm not saying your answer is wrong or in any way worse - it's just that I got the impression you think it's good because it's recursive. IMO, in C++ particularly, that bias can lead to slow and even broken programs. Slow programs because you're growing a huge stack, causing cache and virtual memory paging. Broken programs because you get a stack overflow where an iterative solution would work.

Some would look at your answer and think it's tail recursive and would be optimised into iteration anyway. Of course that's not true - after each recursive call exits, there is a multiply still to do, so it is not tail recursive. The thing is, in C++, there are a lot of more subtle things that prevent tail recursion optimisations - even if the compiler does them at all. For example...

void myrecurse (plan *p)
{
  plan i;
  i.prev = p;
  //  more plan setup, checks, and special case handling

  myrecurse (&i);
}

In this case, all the "plan" instances must remain on the stack. Therefore, stack frames cannot be discarded. Therefore this is not optimizable into iteration, even though there are precisely zero operations done after the recursive call. Not even hidden operations like destructor cleanups, since plan is assumed to be a POD struct.

Incidentally, this is based on something I've done in real code - a data structure operation that is planned during the recursion, but nothing is changed in the original nodes until the recursion reaches the root/leaf, all new nodes needed have been successfully allocated, all locks acquired, and there's no curruption to make worse. At that point, an iteration is done through that linked list of plan instances to commit the changes - the logic was clearer as an iteration than being broken up into fragments relating to the unwinding of the recursive calls.

The point here obviously isn't to claim that recursion is automatically bad. It just makes me nervous when people seem to assume recursion is better than iteration by default.

Steve314