我正在使用以下代码完成一个非常简单的programming excersize:
using System;
namespace Factorial
{
class MainClass
{
static int fives(int x) {
int r = 0;
while(x % 5 == 0) {
r++;
x /= 5;
}
return r;
}
static int z(int x) {
if (x == 1)
return 0;
else
return z (x-1) + fives (x);
}
public static void Main (string[] args)
{
int testCases = Convert.ToInt32 (Console.ReadLine ());
int[] xs = new int[testCases];
for (int i=0; i<testCases; i++)
xs [i] = Convert.ToInt32 (Console.ReadLine ());
foreach (int x in xs)
Console.WriteLine (z (x));
}
}
}
对于小数字似乎工作正常,但是从示例中的8735373打印出“Segmentation fault:11”。是否因为递归太深而导致内存不足?是什么原因造成的?
(我在Mac上运行Mono 2.10.8中的C#。)
P.S。:如果有人对excersize本身感兴趣,here's my final solution(更加优化)。
答案 0 :(得分:4)
这看起来像一个未处理的StackOverflowException
- 在过度使用递归时很常见。所以... 不要过度使用递归。它可能适用于数学和一些非常特定的语言(F#可能会应付),但C#......不是那么多。
看起来像(未经验证):
static int z(int x)
{
int accumulator = 0;
while(x!=1)
{
accumulator += fives(x);
x--;
}
return accumulator;
}
没有错误 - 它没有递归(虽然它每次迭代都会调用fives
)。更好的是:做代数找到直接公式。
答案 1 :(得分:2)
当您使用较大的数字时,您的递归步骤会导致StackOverflowException,如果您查看调试器,您将看到异常发生的递归步骤数。
我认为Mono代码会以某种方式考虑到Segmentaiton错误的堆栈溢出异常,这可能是它的处理方式。
如果您愿意,可以调试它:How do I debug a segmentation fault in Mono on Ubuntu without any debugger?
答案 2 :(得分:1)
似乎从递归到循环的简单转换解决了这个问题:
static int z (int x)
{
int result = 0;
for (int i=1; i<=x; i++) {
result += fives (i);
}
return result;
}
答案 3 :(得分:1)
如果问题是由大量递归引起的,则错误可能是StackOverflowException。正如golergka先前所说,我很确定这是一个单声道故障。当内存通过尝试访问不应达到的内存地址而被错误管理时,会出现分段错误。这种类型的错误是系统错误......而不是C#异常。我几乎可以肯定,Mono并没有很好地管理内存。我希望这对你的研究有所帮助。