Why is this recursive function exceeding call stack size?

1.3k Views Asked by At

I'm trying to write a function to find the lowest number that all integers between 1 and 20 divide. (Let's call this Condition D)

Here's my solution, which is somehow exceeding the call stack size limit.

function findSmallest(num){
    var count = 2
    while (count<21){
        count++
        if (num % count !== 0){
            // exit the loop
            return findSmallest(num++)
        }

    }
    return num
}

console.log(findSmallest(20))

Somewhere my reasoning on this is faulty but here's how I see it (please correct me where I'm wrong):

Calling this function with a number N that doesn't meet Condition D will result in the function being called again with N + 1. Eventually, when it reaches a number M that should satisfy Condition D, the while loop runs all the way through and the number M is returned by the function and there are no more recursive calls.

But I get this error on running it:

function findSmallest(num){ ^

RangeError: Maximum call stack size exceeded

I know errors like this are almost always due to recursive functions not reaching a base case. Is this the problem here, and if so, where's the problem?

2

There are 2 best solutions below

0
On BEST ANSWER

I found two bugs.

  • in your while loop, the value of count is 3 to 21.
  • the value of num is changed in loop. num++ should be num + 1

However, even if these bugs are fixed, the error will not be solved. The answer is 232792560. This recursion depth is too large, so stack memory exhausted.

For example, this code causes same error.

function foo (num) {
    if (num === 0) return
    else foo(num - 1)
}

foo(232792560)

Coding without recursion can avoid errors.

0
On

Your problem is that you enter the recursion more than 200 million times (plus the bug spotted in the previous answer). The number you are looking for is the multiple of all prime numbers times their max occurrences in each number of the defined range. So here is your solution:

function findSmallestDivisible(n) {
    if(n < 2 || n > 100) {
    throw "Numbers between 2 and 100 please";
  }
    var arr = new Array(n), res = 2;
  arr[0] = 1;
  arr[1] = 2;
  for(var i = 2; i < arr.length; i++) {
    arr[i] = fix(i, arr);
    res *= arr[i];
  }
  return res;
}

function fix(idx, arr) {
    var res = idx + 1;
  for(var i = 1; i < idx; i++) {
    if((res % arr[i]) == 0) {
        res /= arr[i];
    }
  }
  return res;
}

https://jsfiddle.net/7ewkeamL/