-3

I'm trying to implement a recursive power function in C++, but it fails with large n due to stack overflow. Here's the code:

class Solution {
public:
    double myPow(double x, int n) {
        long long exp = n;
        if (exp < 0) {
            x = 1 / x;
            exp = -exp;
        }
        return pow(x, exp);
    }

    double pow(double x, long long n) {
        if (n == 0) return 1;
        return x * pow(x, n - 1); // Recursive call
    }
};

It works fine for small values of n, but when I run it for large values like

myPow(2.0, 1000000000)

, I get a stack overflow error.

What I Want to Know:

Why is this recursive code causing a stack overflow?

What's the best way to optimize this implementation?

Should I use iteration or a different recursion pattern?

What I’ve Tried:

I tried using long long to avoid integer overflow.

I suspect too many recursive calls might be the issue.

8
  • 2
    First notice you ask for n recursive calls, so you can explode the stack just for that, second if n is negative because of an overflow when the compiler read it you have much more chance to explode it, how can you be surprised ? Notice you do not need at all to have recursive call to compute the result Commented May 27 at 15:25
  • 3
    You should use iteration, but a much more efficient algorithm, whether using iteration or recursion, is exponentiation by squaring. Commented May 27 at 15:28
  • 3
    Do you understand what a "stack overflow" is? Do you understand that myPow(2.0, 1000000000) would require 1 billion stack frames? Do you understand what your code is going to do with myPow(2.0, -1)? Commented May 27 at 16:38
  • 2
    Welcome to Stackoverflow! Commented May 27 at 16:40
  • 3
    "Why is this recursive code causing a stack overflow?" - because recursive function calls take up stack space and the size of the stack is limited, so you run out of available space. It's really that simple. Commented May 27 at 17:44

2 Answers 2

4

You current implementation makes one recursive call for each decrement of n, so for n = 1,000,000,000, you're doing 1 billion recursive calls, which will overflow the stack because the call stack depth is limited (usually < 1000 to a few thousand by default).

To optimize the code you will have to reduce the number of recursive calls. The optimal approach is called Exponentiation by Squaring, which brings time complexity down to O(log n) you can read more about it from here: https://www.freecodecamp.org/news/binary-exponentiation-algorithm-explained-with-examples/.

Yes, it can be done by iterative approach as well, the code will look like something as following

class Solution {
public:
    double myPow(double x, int n) {
        long long exp = n; 
        if (exp < 0) {
            x = 1 / x;
            exp = -exp;
        }

        double result = 1.0;

        while (exp > 0) {
            if (exp % 2 == 1) {
                result *= x;
            }
            x *= x;
            exp /= 2;
        }

        return result;
    }
};
Sign up to request clarification or add additional context in comments.

1 Comment

"The optimal approach is called Exponentiation by Squaring" If this was CS@SE, you'd have incurred the wrath of all the stickler there. (It is a decent approach…)
3

While Rimsha Chaudhry's answer is correct, if (and you can't count on this) you use a C++ compiler that performs tail-call elimination, and this optimization is enabled, you can still perform this recursively without the stack overflow by passing an accumulator that builds up the result.

Because this information is passed along to each call through that accumulator argument, there is no need to reference back to any previous calls, and the stack space for one call to pow can be reused, preventing a stack overflow.

double pow(double x, long long n, double acc=1.0) {
    if (n == 0) return acc;
    return pow(x, n - 1, acc * x);
}

See also: Which, if any, C++ compilers do tail-recursion optimization?

Note that without resolving the recursion that's causing the stack to overflow, a stack overflow will occur before integer overflow becomes a concern.

1 Comment

Independently of the fact I agree with you, several decades ago some Lisp interpreter and compiler was able to detect specific cases of wrapped recursion to not fill the stack, I did that myself in 1984 even it was programing in assembler 6809 on a Goupil 3 with harder conditions than now, it is strange that management was lost

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.