使用递归来求和数

时间:2009-04-24 13:40:25

标签: recursion

我刚刚研究了递归的概念,我想我会尝试一个简单的例子。在下面的代码中,我试图获取数字:1,2,3,4,5,并使用递归将它们一起添加。我预计结果为15,但我的代码返回16。

我做错了什么?

代码:

    static void Main(string[] args)
    {

        Console.WriteLine(Sum(5));
        Console.Read();
    }


    static int Sum(int value)
    {
        if (value > 0)
        {
          return value + Sum(value - 1);
        }
        else
        {
            return 1;
        }
    }

16 个答案:

答案 0 :(得分:35)

你在else子句中返回1。你应该回来0:

else
{
    return 0;
}

如果该值不大于零,为什么你会首先返回一个?

答案 1 :(得分:17)

您的代码执行如下:

Sum --> 5
  Sum --> 4
    Sum --> 3
      Sum --> 2
        Sum --> 1
          Sum --> 0
          1 <---
        2 <---
      4 <---
    7 <---
  11 <---
16 <---

检查你的基本情况。

答案 2 :(得分:13)

其他人已经注意到了错误,我将详细说明递归。

虽然C#当前不执行尾调用优化(尽管IL有特殊的tail指令),但值得一提的是尾递归通常是一件好事。

Tail recursion是递归的一种特殊情况,其中函数的最后一个操作(尾调用)是递归调用。由于最后一次调用是递归调用,因此不需要保留调用函数的堆栈帧,并且编译器可以轻松地使用该信息来生成机器指令,使得堆栈根本不增长。所以它基本上可以将递归函数转换为迭代函数。

重写代码以支持尾递归可以按照以下方式完成:

static int Sum(int result, int value)
{
    if(value == 0)
        return result;

    return Sum(result + 1, value - 1);
}

答案 3 :(得分:7)

static int Sum(int value)
{
    if (value > 0)
    {
        return value + Sum(value - 1);
    }
    else
    {
        return 0; //Change this.
    }
}

答案 4 :(得分:5)

那是因为,当值为= 0时,返回1.然后它被添加。

Sum的“else”子句应该返回0。

答案 5 :(得分:4)

我总是喜欢将终止案件放在前面,这样他们就很明显了,而且我对"if cond then return a else return b"构造产生了一种近乎精神病的暴力仇恨。我的选择是(明确表示它对负数不起作用):

static unsigned int Sum(unsigned int value) {
    if (value == 0)
        return 0;
    return value + Sum(value - 1);
}

我相信这比支撑和控制流程更加可读。

答案 6 :(得分:4)

其他人已经回答了这个问题,但是当我处理递归时,我喜欢做的一件事就是检查基本情况和另外一个案例。我的情况下我会用1测试它,这将产生2.因为这显然是错误的,你可能想要检查0不会使用任何递归,所以很明显错误在于基类。

一般来说递归更容易推理,因为你可以列出你需要检查的有限数量的东西,但它最初需要一个信念的飞跃,因为你的直觉是错误的。只测试边缘情况并信任数学它将从不失败。

答案 7 :(得分:4)

int summation(int num){

    if (num==1)
        return 1;

    return summation(num-1)+num;
}

答案 8 :(得分:1)

我很确定问题是因为您希望递归在value == 1时终止,并且它当前在value == 0时终止。

答案 9 :(得分:1)

您的终止表达方式存在争议。当值== 0(或更低)时,它应该返回0而不是1.为了效率(我们在这里承认,显然不是问题,否则递归不会用于此任务) ,你应该在值== 1处终止递归并返回一个文字1来保存一个不必要的递归级别。

答案 10 :(得分:0)

using System;
using NUnit.Framework;

namespace Recursion
{
  [TestFixture()]
    public class Test
    {
        [Test()]
        public void TestSum ()
        {
            Assert.AreEqual (Sum (new int[] { }), 0);
            Assert.AreEqual (Sum (new int[] { 0 }), 0);
            Assert.AreEqual (Sum (new int[] { 1 }), 1);
            Assert.AreEqual (Sum (new int[] { 1, 2, 3, 4, 5 }), 15);
        }

        public int Sum(int[] head)
        {
            if (head.Length == 0) return 0;

            int[] tail = new int[head.Length - 1];

            for (int i = 1; i < head.Length; i++) 
            {
                tail [i-1] = head [i];
            }

            return head[0] + Sum (tail);
        }
    }
}

答案 11 :(得分:0)

它也可以这样写:

public static int sum(int n){
    int total;

    if(n==1){
        total =1;

    }else{
        total = sum(n-1)+n;
    }
    return total;
}

答案 12 :(得分:0)

实际上,我认为您不需要检查其他情况,因为

public static int sum(int number){
    if(number > 0){
       return number + sum(--number);
    }
    return number; // return 0 so that's why you don't need check else condition
}

答案 13 :(得分:0)

从最后开始,递归Sum方法如下所示:

    // version 3

    public static int Sum(int startRange, int endRange)
    {
        if (endRange > startRange)
        {
            return endRange + Sum(startRange, endRange - 1);

        }

        if (endRange < startRange)
        {
            return startRange + Sum(endRange, startRange - 1);

        }

        return endRange; 

    }

将startRange硬编码为0会给我们:

    // version 2

    public static int Sum(int range)
    {
        if (range > 0)
        {
            return range + Sum(0, range - 1);

        }

        if (range < 0)
        {
            return Sum(range, -1);

        }

        return range;

    }

...如果您只想将方法限制为正数,则无需签名:

    // version 1

    public static unsigned int Sum(unsigned int range)
    {
        if (range > 0)
        {
            return range + Sum(0, range - 1);

        }

        return range;

    }

我希望这有助于通过递归更深入地了解求和数范围。

答案 14 :(得分:0)

        static int Sum(int[] addends)
    {
        if (addends.Length == 1)
        {
            return addends[0];
        }
        else
        {
            int tailIndex = addends.Length - 1;
            var subArray = addends[0..tailIndex];
            return addends[tailIndex] + Sum(subArray);
        }


    }

答案 15 :(得分:-1)

试试这段代码:

def sumr(n): 
    if n==0:
        return n
    return n+sumr(n-1)