无法检测 JS 中的 'while loop' 中无限循环的原因

Can't detect the cause of infinite loop in a 'while loop' in JS

我的 while 循环中有一个无限循环,我找不到原因。

这是一个简单的函数,它 return 是参数数字的总和。我使用 while 循环,因为它需要将数字相加,直到它落在一位数字上。 我确保我添加了一条语句,以确保在某个点循环会中断。但显然不会。

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)

我收到一条警告,提示我在第 4 行(while 循环)有一个无限循环。 我希望 num=sum 将新整数(位数减少)重新分配给 num 变量,从而在某个时候跳出循环。这有错吗?

更让我困惑的是,我用来调试问题的大多数 JS 编辑器 return 输出,但这需要很长时间。那么这是一个无限循环还是不是?

您有一个嵌套循环结构,其中第一个条件始终为真。

如果只获取小于 10 的数字,您可以再次调用该函数作为递归。

function digital_root(n) {
    var num = n.toString(), // declare and use the string value
        sum = 0,
        i;

    for (i = 0; i < num.length; i++) {
        sum += parseInt(num[i], 10)
    }
    return sum > 9
        ? digital_root(sum)
        : sum;
}

console.log(digital_root(456));

既然你已经得到了答案,这里是满足结果的另一种方法

function digital_root(n) {
  // convert the number to string
  // use split to create an array of number viz ['4','5','6']
  // use reduce to sum the number after converting to number
  // 0 is the initial value
  return n.toString().split('').reduce((a, c) => a + parseInt(c, 10), 0)
}
console.log(digital_root(456))

避免所有导致您所面临情况的嵌套循环,我宁愿以更易读的方式进行。

function digital_root(n) {
    sum = n;

    while(sum.toString().length > 1) {
        sum = sum.toString()
       .split('')
       .map(digit => parseInt(digit, 10))
       .reduce((acc, cur) => acc + cur);
    }

    return sum;
}

console.log(digital_root(456));

在 re-reading 这个问题之后,我注意到您正在尝试将整数缩减为单个数字。您的代码的问题是 sum 仅在 while 循环之前设置为 0。这意味着它没有为第二个、第三个...重置。运行.

sum = 0 移动到 while 循环中解决了这个问题。我还在顶部添加了变量声明以避免设置全局变量。

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));

这里用递归的方式写的,我个人比较喜欢的风格:

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));