Search code examples
javascriptarraysfor-loopinfinite-loopprime-factoring

Why does my loop gone infinite loop?


I am writing a function that will find prime factors of a number. In that function, it has got two loops. One for finding factors, another for finding prime factors from the first loop. The second loop has gone infinite, I haven't spotted anywhere in the loop that could make it infinite. Where did I miss?

function findPrimeFactors(num)
{
 var factors = [];
 var primeFactors = [];
 var currIndex = 0;
 var initFactorsLen;
 var currCompose;
 for (i = 1; i <= num; ++i)
 {
  if (num % i == 0)
  {
   factors.push(i);
  }
 }
 var initFactorsLen = factors.length;
 for (i = 0; i <= initFactorsLen; ++i) 
 {
 //This is infinite loop
  console.log("i is " + i + " and factors are " + factors);
  currCompose = factors[i];
  var primeTest = isPrime(currCompose); 
  if (primeTest == true)
  {
   primeFactors.push(currCompose);
  }
 }
 return primeFactors;
}

function isPrime(num)
{
 var sqrtNum = Math.sqrt(num);
 var ceiledNum = Math.ceil(sqrtNum);
 if (num == 1 || num == 0)
 {
  return false;
 }
 else if (num == 2)
 {
  return true;
 }
 else
 {
  for (i = 2; i <= ceiledNum; ++i)
  {
   if (num % i == 0 && i != num)
   {
    return false;
   }
  }
  return true;
 }
}

I've also notice that sometimes it doesn't gone infinite, but it returns only one prime number although it has 2. (Try findPrimeFactors(143))

Thanks,


Solution

  • Your i loop variable is global, so both functions share the same values for i.

    Initialize and declare it with var, like this:

    for (var i = 0; i <= initFactorsLen; ++i)
    

    An alternative to declaring it within the loop statement is to declare it with your other variables. Note that you can declare all your variables in a comma-separated list, like this:

    var factors = [],
        primeFactors = [],
        currIndex = 0,
        initFactorsLen,
        currCompose,
        i;
    

    Also note that you don't need to explicitly check for truthness. This:

    var primeTest = isPrime(currCompose); 
    if (primeTest == true) {
      primeFactors.push(currCompose);
    }
    

    … is equivalent to this:

    var primeTest = isPrime(currCompose); 
    if (primeTest) {
      primeFactors.push(currCompose);
    }
    

    … or more simply:

    if (isPrime(currCompose)) {
      primeFactors.push(currCompose);
    }