Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# isPowerOf function

I have the next function:

static bool isPowerOf(int num, int power)
{
        double b = 1.0 / power;
        double a = Math.Pow(num, b);
        Console.WriteLine(a);
        return a == (int)a;
}

I inserted the print function for analysis.

If I call the function:

isPowerOf(25, 2)

It return true since 5^2 equals 25. But, if I call 16807, which is 7^5, the next way:

isPowerOf(16807, 5)

In this case, it prints '7' but a == (int)a return false.

Can you help? Thanks!

like image 890
Novak Avatar asked Jul 06 '12 09:07

Novak


2 Answers

Try using a small epsilon for rounding errors:

return Math.Abs(a - (int)a) < 0.0001;

As harold suggested, it will be better to round in case a happens to be slightly smaller than the integer value, like 3.99999:

return Math.Abs(a - Math.Round(a)) < 0.0001;
like image 60
Dani Avatar answered Sep 28 '22 04:09

Dani


Comparisons that fix the issue have been suggested, but what's actually the problem here is that floating point should not be involved at all. You want an exact answer to a question involving integers, not an approximation of calculations done on inherently inaccurate measurements.

So how else can this be done?

The first thing that comes to mind is a cheat:

double guess = Math.Pow(num, 1.0 / power);
return num == exponentiateBySquaring((int)guess, power) ||
       num == exponentiateBySquaring((int)Math.Ceil(guess), power);
       // do NOT replace exponentiateBySquaring with Math.Pow

It'll work as long as the guess is less than 1 off. But I can't guarantee that it will always work for your inputs, because that condition is not always met.

So here's the next thing that comes to mind: a binary search (the variant where you search for the upper boundary first) for the base in exponentiateBySquaring(base, power) for which the result is closest to num. If and only if the closest answer is equal to num (and they are both integers, so this comparison is clean), then num is a power-th power. Unless there is overflow (there shouldn't be), that should always work.

like image 21
harold Avatar answered Sep 28 '22 03:09

harold