tags:

views:

448

answers:

2

Is there any predefined function in c++ to check whether the number is square of any number and same for the cube..

+5  A: 

sqrt(x), or in general, pow(x, 1./2) or pow(x, 1./3)

For example:

int n = 9;
int a = (int) sqrt((double) n);
if(a * a == n || (a+1) * (a+1) == n)  // in case of an off-by-one float error
    cout << "It's a square!\n";

Edit: or in general:

bool is_nth_power(int a, int n) {
  if(n <= 0)
    return false;
  if(a < 0 && n % 2 == 0)
    return false;
  a = abs(a);

  int b = pow(a, 1. / n);
  return pow((double) b, n) == a || pow((double) (b+1), n) == a;
}
Jesse Beder
The problem with using `pow(x, 1./3)` is that 1/3 does not have an exact representation in floating point, so you're not "really" getting the cube root. C99 onwards has `cbrt`, which should do a better job of getting the cube root.
Chris Jester-Young
I suppose. But `pow` generalizes easier, and it's easy enough to correct for floating point errors.
Jesse Beder
+1  A: 

No, but it's easy to write one:

bool is_perfect_square(int n) {
    if (n < 0)
        return false;
    int root(round(sqrt(n)));
    return n == root * root;
}

bool is_perfect_cube(int n) {
    int root(round(cbrt(n)));
    return n == root * root * root;
}
Chris Jester-Young
Where do you see a possible division by zero ? sqrt(0) and cbrt(0) are defined.
Pierre Bourdon
The original answer I had in my mind used return `n / root == root`, but I ended up using a different approach. Thanks for pointing out! Will edit answer.
Chris Jester-Young
This won't always work, due to floating-point error: if `sqrt()` or `cbrt()` happens to return epsilon less than the actual root, the cast to an integer will truncate that, and the check will fail. To be completely bullet-proof against that, you also need to check if `n == (root + 1) * (root + 1)` for the square root case or if `n == (root + 1) * (root + 1) * (root + 1)` for the cube root case.
Adam Rosenfield
Oh god, it hurts my head. I kept looking for the "root" function until I realized you were just initializing an integer... I strongly dislike your coding style.
Mark
@Adam: Do you have a case where an "integral" result from `sqrt` or `cbrt` would end up to be "epsilon less than the root"? Remember we're not dealing with fractions here, so (assuming that the root isn't so big that it can't be represented exactly by a floating point number, in which case we've lost already), how will this be a problem? I'm happy to use `round()` though.
Chris Jester-Young
@Mark: You can dislike it all you want, but it's the "more-standard" initialisation style in C++; I think it's called "constructor syntax" or something like that. i.e., if you are constructing an object that, say, takes more than one constructor parameter, you'd have to use that syntax anyway. I don't like to make a special exception for numeric types, so I use constructor syntax for them too.
Chris Jester-Young