我刚刚研究了递归的概念,我想我会尝试一个简单的例子。在下面的代码中,我试图获取数字: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;
}
}
答案 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)