-1

We say p is the perfect pth power of a number x if x can be expressed as another number b^p.

i.e if x=b^p , then p is the perfect pth power of x.

I have few use cases where x can be either a positive integer, negative integer or even a fraction. The first two cases can be handled easily in java, but how to find out the perfect pth power of a number x using java, when x is a fraction. Is it not true that if x is a fraction, we can simply use Math.sqrt(x) and get a number b such that b^2 =x? Then 2 will be the perfect pth power of x. Is this case even valid?

I am not necessarily looking for code, but the logic to determine the perfect pth power of x in java if x is a fraction. Also please do state your reason if anyone thinks this case is invalid.

Below is the code I wrote to handle cases where x is either a positive integer or a number between 0 and 1. But can we handle cases where x is, say for eg. 45.487,875515.54884, etc?

public class PerfectPower {

public PerfectPower() {

    }

    public Integer getPerfectPower(double x){

        // x=b^p

        int p = 0;
        double b;

        if(x==0){
            throw new IllegalArgumentException("Cannot accept number 0.");
        }

        if (x > 1) {
            for (b = 2; b <= x; b++) {

                double value = 0;
                p = 1;

                while (value <= x) {

                    value = Math.pow(b, p);

                    if (value == x) {
                        return p;
                    } else if (value > x) {
                        break;
                    } else {
                        p++;
                    }
                }

            }
        } else if(x>0 && x<1){

            for (b = 2; (1/b) >= x; b++) {

                double value = 1;
                p = -1;

                while (value >= x) {

                    value = Math.pow(b, p);

                    if (value == x) {
                        return p;
                    } else if (value < x) {
                        break;
                    } else {
                        p--;
                    }
                }

            }

        }

        return null;

    }
anonymous
  • 11
  • 4
  • 1
    This is not a question for stackoverflow as it is written. Make it into a coding question by adding some code or you will continue to see down votes. – Joakim Danielson Sep 01 '18 at 06:24
  • Added code to support the question. – anonymous Sep 01 '18 at 06:34
  • I don’t get it. If only x is given, can’t you just set b = x and p = 1? Or if b != x is required, then b = sqrt(x) and p = 2? – Ole V.V. Sep 01 '18 at 06:36
  • I scenario is that any random number x could be passed to the program. If 81 is passed, the smallest numbers b and p such that b^p = 81 will be b=3 and p=4. So the perfect power of 81 is 4. Similarly for 16, p=4 as 2^4=16. – anonymous Sep 01 '18 at 06:43
  • @anonymous What exactly is the problem? You can just calculate the n-th root of `x` and power it by `n` again (which will be your `p`). – Progman Sep 01 '18 at 08:54
  • Are b and p required to be integral? Are you after the smallest possible b and/or the greatest possible p? – Ole V.V. Sep 01 '18 at 11:49
  • I am positively surprised how well your code works for fractional numbers between 0.0 and 1.0. `getPerfectPower(1.0 / 1771561.0)` correctly returns `-6` (the argument equals 11^-6). We should have expected problems from imprecision when you compare double values using equality, as in `value == x`. – Ole V.V. Sep 01 '18 at 14:15

2 Answers2

0

Since 45 487.875 515 548 84 (to take this as an example) is not integral, the only way it can be expressed as b ^ p where b and p are integral, is if p is negative. That is, your number may be the square root, the cube root, the fourth root, etc., of some (large) integer.

The first question is that of precision. Your number cannot be represented precisely in a Java double. You may use a BigDecimal. It also cannot be precisely some root of some integer, so you will have to decide a tolerance to accept.

As far as I can tell, your big problem is that the range of possible p values is infinite. It may even be so that all numbers are close enough to the pth root of some (large) integer that you cannot reasonably distinguish; I don’t know, and it surely depends on your tolerance.

I think the best thing you can try is to raise your number to 2, 3, 4, etc., and see when you come close to a whole number. If your number raised to the power of q is close enough to a whole number, return -q as your p. And stop searching before you lose your patience. :-)

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

We can do this in a simple way using logarithms. It goes as below:

x = b^p    log(base b)x = p     log x/log b = p  

So we can iterate b = 2 through x and check whether p is a perfect integer and return the value. For decimal cases we can tweak the log formula some more.

log b = (log x)/p    Hence b = 10^(log x)/p) 

In each iteration we can check whether b^p = x and if it is return p. I solved this problem assuming p should be an integer. However for cases where p can be decimal and x between 0 to 1 this solution should be tweaked some more. Below is my code which I have implemented in scala.

def perfectpowerlog(x: Double): Double = {
    var i: Double = 2
    var n: Double = 1
    var p: Double = 0
    val loop = new Breaks
    if (x == 1) {
        return n
    }
    if (x.ceil == x) {
        loop.breakable {
            while (i<=x) {
                p = math.log(x)/math.log(i)
                if (p.toInt == p) {
                    n = p
                    loop.break()
                }
                else
                    i=i+1
            }
        }
    }
    else {
        loop.breakable {
            while(i<=x.ceil) {
                p = pow(10,(log10(x)/i))
                if(pow(p,i) == x) {
                    n = i
                    loop.break()
                }
                else
                    i = i+1
            }
        }
    }
    return n
}
Alperen
  • 3,772
  • 3
  • 27
  • 49