Ad

Can't Detect The Cause Of Infinite Loop In A 'while Loop' In JS

I've got an infinite loop inside my while loop and I can't find the cause.

It's a simple function that returns the sum of the argument's digits. I use a while loop because it needs to add up the digits until it lands at a one digit number. I made sure that I added a statement that would make sure that at a certain point the loop will break., But it obviously doesn't.

function digital_root(n) {
 num = n;
 sum = 0;
 while (num.toString().length>1){
      for (i=0; i<num.toString().length; i++) {
           sum += parseInt(num.toString()[i])    
       }
       num = sum;
  }
  return sum;
}
digital_root(456)

I get a warning that I have an infinity loop on line 4 (while loop). I hoped that num=sumwould reassign the new integer (with reduced number of digits) to the numvariable and thus at some point break out of the loop. Is this wrong?

What further confuses me is that most of the JS editors I've used to debug the problem return an output, but it takes ages. So is it an infinite loop or is it not?

Ad

Answer

After re-reading the question I noticed that you're trying to reduce an integer down to a single number. The issue with your code was that sum was set to 0, only before the while loop. Meaning that it didn't reset for the second, third, ... run.

Moving sum = 0 into the while loop resolves this issue. I've also added variable declarations at the top to avoid setting global variables.

function digital_root(n) {
  var num, sum, i;

  num = n;
  while (num.toString().length > 1) {
    sum = 0;
    for (i = 0; i < num.toString().length; i++) {
      sum += parseInt(num.toString()[i]);
    }
    num = sum;
  }
  return sum;
}

console.log(digital_root(456));

Here written in a recursive manner, a style that I personally more prefer:

function digital_root(integer) {
  // guard against things that might result in an infinit loop, like floats
  if (!Number.isInteger(integer) || integer < 0) return;
  
  const chars = integer.toString().split("");
  if (chars.length == 1) return integer;
  
  return digital_root(
    chars.map(char => parseInt(char))
         .reduce((sum, digit) => sum + digit)
  );
}

console.log(digital_root(456));

Ad
source: stackoverflow.com
Ad