Writing a Power method with a minimum amount of steps n(log)N

时间:2019-04-08 12:48:00

标签: java

I'm trying to write the Power method and now the question is how to write it in a better way. Here is my code, I've verified it works well for all the Power conditions, however I can't think on a better solution.

The real issue is how I express the power with a Negative exponent in O(log)n condition

public static double raiseToPowerIterative(double x, int n) {
    double sol = 1;
    if (n == 0) {
        return 1;
    }
    if (n > 0) {
        for (int i = 1; i <= n;i++) {
            sol *= x;
        }
        return sol;
    } else if (n < 0){
        for (int i = -1; i >= n; i--) {
            sol /= x;
        }
    }
    return sol;
}

1 个答案:

答案 0 :(得分:0)

You need some additional math rules, you are using:

  • xn = x.x. ... .x (n times)

With O(n)

However

  • x2k = xk . xk
  • x2k+1 = x.x2k

Which can deliver O(²log n), as you are doing exponents n → n/2 → n/2/2 → ... → 1.

Where you only need to calculate xk once.

A recursive solution might be easiest; calling oneself for xk.


Your solution:

That does not work, I think. As probably past limit date of the work.

Wrong:

double power(double x, int n) {
    if (n == 0) {
        return 1;
    }
    boolean negative = ( n < 0 );
    if (negative) {
        n = -n;
    }
    double sol = 1;
    while (n > 0) {
        if (n%2 == 1) {
           sol *= x;
        }
        x *= x;
        n /= 2;
    }
    if (negative) {
        return 1 / sol;
    }
    return sol; 
}

Correct recursive:

double power(double x, int n) {
    if (n == 0) {
        return 1;
    } else if (n < 0) {
        return 1 / power(x, -n);
    }
    double sqrPower = power(x, n/2);
    int p = sqrPower * sqrPower;
    if (n % 1 == 1) {
        p *= x;
    }
    return p;
}

That is, one has to do something with the result of the recursive call. For an iterative loop one would need a stack to reconstruct the result.

Correct iterative:

double power(double x, int n) {
    if (n == 0) {
        return 1;
    }
    boolean invert = n < 0;
    if (invert) {
        n = -n;
    }
    Stack<Double> factors = new Stack<>();
    while (n > 0) {
        factors.push(n % 1 == 1 ? x : 1.0);
        n /= 2;
    }
    double sol = 1;
    while (!factors.empty()) {
        double f = factors.pop();
        sol = sol * sol * f;
    }
    return invert ? 1/sol : sol;
}