如何递归地对数字进行求和javascript

时间:2018-02-20 20:41:08

标签: javascript recursion

我正在学习JavaScript的基础知识,并试图编写一个递归函数来将一组整数加在一起。例如,函数参数为1234,结果应为10。这就是我到目前为止所拥有的......

function sumDigits(numbersStr) {

  var numToString = numbersStr.toString()
  var numArr = numToString.split('').map(Number);

  var sum = 0;

  // base case
  if (numArr.length === 0) {
    return sum
  } 

  // recursive case
  else {
    var popped = numArr.pop();
    sum+=popped;
    return sumDigits(numArr);

  }
}

但每当我运行它时,我会得到一个无限循环(我的标签崩溃)。如果我弹出数组的最后一个元素,将其添加到sum变量,然后在缩短的数组上再次调用该函数,那为什么我会得到一个无限循环?非常感谢!

8 个答案:

答案 0 :(得分:3)

你的代码中的问题是sumDigits期望得到一个数字,但在递归中你传递一个数字数组。

答案 1 :(得分:2)

您可以使用字符串或数字作为函数的参数,并将值转换为字符串。

然后检查长度并在长度为零时返回零(通常是退出条件)。

如果不返回第一个字符的值,则使用索引1中的切片字符串添加调用函数的结果。

基本上,recurisve函数有两个部分。

  1. 具有退出值的退出条件。这取决于递归函数的目的。它通常是一个中性值,如加法为零,或乘法为1

  2. 执行值表示算术运算,再次使用减少的字符串/数组或数值调用函数。

  3. function sumDigits(num) {
        num = num.toString();
        return num.length === 0
            ? 0
            : +num[0] + sumDigits(num.slice(1));			
    }
    
    console.log(sumDigits(1234));

    另一种方法是使用tail recursion,它不会为每个调用函数扩展堆栈,因为函数以调用结束,而不保留上面函数中的临时值,实际数值{{ 1}}和等待执行adition。

    在这种情况下,您可以存储中间结果以及调用函数。

    +num[0]

答案 2 :(得分:1)

function digitCount(num) {
     let val1 = num % 10
let rem = Math.floor(num / 10)
return val1 + (rem != 0 ? digitCount(rem) : 0)
}

console.log(digitCount(87))

答案 3 :(得分:0)

问题是你的函数接受一个数字作为它的参数,但是当你递归地使用它时,你会给它一个数组。我建议将递归部分拉入自己的辅助函数,如下所示:

public class Parent
{
    [Key]
    public Guid Id { get; set; }
    public virtual ICollection<Child> Children { get; set; }
}

public class Child 
{
    [Key]
    public Guid Id { get; set; }
    public Guid ParentId { get; set; }

    [ForeignKey("ParentId")]
    public virtual Parent Parent { get; set; }
}

答案 4 :(得分:0)

你的函数需要一个字符串,但在递归调用中,你传递一个数组。

此外,您已拨打.map不需要的电话,因为您可以将.split数组中的字符串转换为数字,只需预先设置+对他们来说。

你有什么理由不使用Array.reduce吗?

&#13;
&#13;
function sumDigits(stringOfNums) {
  // Split the string into an array of strings. Reduce the array to the sum by 
  // converting each string to a number.
  console.log(stringOfNums.split('').reduce(function(x,y){ return +x + +y}, 0));
}
sumDigits("1234");
&#13;
&#13;
&#13;

答案 5 :(得分:0)

在递归调用中传递数组将保证其.toString()永远不会为空,因为逗号将添加的字符数多于已删除的字符数。

相反,请以数学方式进行,这样您就不需要数组甚至字符串转换。

function sumDigits(num) {
  return num ? (num%10) + sumDigits(Math.floor(num/10)) : 0
}

console.log(sumDigits(1234))

这假设传递了一个正整数。如果可以提供其他输入,您将需要额外的警卫。

答案 6 :(得分:0)

无需将数字转换为数组。您可以使用0获取数字的最后一位数字,并使用number % 10删除该数字。然后递归,直到数字为Math.floor(number / 10)

0

答案 7 :(得分:0)

巴尔玛有很好的理智。从数字转换为字符串然后再转换回数字有点傻​​。另外,如果这是一项家庭作业,使用像String.prototype.split这样的高级功能可能不会教你很多。

这是一个使用功能风格编写的尾递归版Barmar程序

  • 基本情况 - 输入数字n为零,返回累加器acc
  • 归纳案例 - n 零;重复使用下一个n和下一个acc

&#13;
&#13;
const sumDigits = (n = 0, acc = 0) =>
  n === 0
    ? acc
    : sumDigits (n / 10 >> 0, acc + n % 10)

console.log (sumDigits ())     // 0
console.log (sumDigits (1))    // 1
console.log (sumDigits (12))   // 3
console.log (sumDigits (123))  // 6
console.log (sumDigits (1234)) // 10
&#13;
&#13;
&#13;