Использование рекурсии для суммирования чисел

Я только что изучал концепцию рекурсии, и я подумал, что попробую простой пример. В следующем коде я пытаюсь взять числа: 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;
        }
    }

Ответ 1

Вы возвращаете 1 в предложении else. Вы должны возвращать 0:

else
{
    return 0;
}

Если значение не больше нуля, почему вы должны вернуть его в первую очередь?

Ответ 2

Ваш код выполняется следующим образом:

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

Проверьте базовый футляр.

Ответ 3

Другие уже заметили ошибку, и я расскажу о рекурсии.

Хотя С# в настоящее время не выполняет оптимизацию хвостовых вызовов (хотя IL имеет специальную инструкцию tail), стоит упомянуть, что хвостовая рекурсия обычно хороша.

Рекурсия хвоста является частным случаем рекурсии, в которой последняя операция функции, хвостовой вызов, является рекурсивным вызовом. Поскольку последний вызов является рекурсивным вызовом, нет необходимости сохранять стек стека вызывающей функции, и компилятор может легко использовать эту информацию для генерации машинной команды, так что стек не растет вообще. Таким образом, он может в основном превратить рекурсивную функцию в итеративный.

Переписывание кода для поддержки рекурсии хвоста может быть выполнено следующим образом:

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

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

Ответ 4

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

Ответ 5

Это потому, что, когда значение равно = 0, вы возвращаете 1. Затем он добавляется.

Сумма "else" должна возвращать 0.

Ответ 6

Я всегда предпочитаю положить завершающий регистр вперед, чтобы они были очевидны, и у меня есть жестокая почти психопатическая ненависть к конструкциям "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);
}

Я считаю, что это гораздо более читаемо, чем болото скобок и поток управления.

Ответ 7

Другие уже ответили на этот вопрос, но когда я работаю с рекурсией, одна из вещей, которые мне нравится делать, чтобы проверить, что она работает, - это использовать базовый случай и один дополнительный случай. В вашем случае я проверил бы его с 1, что даст 2. Так как это, очевидно, неправильно, вы можете проверить на 0, который не собирается использовать какую-либо рекурсию, и поэтому должно быть очевидно, что ошибка лежит в базовом классе.

В целом рекурсия легче рассуждать, поскольку вы можете перечислить ограниченное количество вещей, которые вам нужно проверить, но изначально требуется скачок веры, поскольку ваша интуиция будет неправильной. Просто проверяйте случаи кросс и доверяйте математике, это никогда не потерпит неудачу.

Ответ 8

int summation(int num){

    if (num==1)
        return 1;

    return summation(num-1)+num;
}

Ответ 9

Я уверен, проблема в том, что вы хотите, чтобы ваша рекурсия завершилась, когда value == 1, и она в настоящее время завершается, когда value == 0.

Ответ 10

Ваше завершающее выражение не работает. Когда value == 0 (или ниже), оно должно возвращать 0, а не 1. Для эффективности (что, допустим, здесь, очевидно, не является проблемой, иначе рекурсия не была бы использована для этой задачи), вы должны завершить рекурсию со значением == 1 и вернуть литерал 1, чтобы сохранить один ненужный уровень рекурсии.

Ответ 11

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

Ответ 12

Он также может быть записан следующим образом:

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

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

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

Ответ 13

На самом деле, я думаю, вам не нужно проверять дело иначе, потому что

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

Ответ 14

Чтобы начать в конце, рекурсивный метод 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;

    }

Надеюсь, что это поможет получить больше информации о суммировании диапазонов чисел через рекурсию.

Ответ 15

Попробуйте этот код:

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