我正在使用Project Euler编号5.我没有使用Google搜索,因为这通常会导致SO得到答案。所以,这就是我所拥有的:
private int Euler5(int dividend, int divisor)
{
if (divisor < 21)
{
// if it equals zero, move to the next divisor
if (dividend % divisor == 0)
{
divisor++;
return Euler5(dividend, divisor);
}
else
{
dividend++;
return Euler5(dividend, 1); // move to the dividend
}
}
// oh hey, the divisor is above 20, so what's the dividend
return dividend;
}
在我看来,这是有道理的。然而VS2012给了我一个StackOverFlowException,表明我确保我没有进入无限循环或使用递归。我的问题是,为什么这是一个无限循环?我有一种感觉,我错过了一些完全愚蠢的东西。
修改
由于人们似乎一直在发帖,我会重申我没有使用谷歌这一事实,因为他害怕找到答案。我不想要问题的答案。我只是想知道为什么我会得到例外。
答案 0 :(得分:10)
当然这种逻辑会破坏筹码。想想看,如果你要实现这个逻辑来解决找到可被1-10整除的最小数字的问题,那么根据problem statement,你在堆栈中至少有2520个调用:< / p>
2520是可以除以1到10之间的每个数字的最小数字,没有任何余数。
对于1-20,答案显然要大得多,而且你所吹的堆栈也就不足为奇了。你应该找到一个非递归的解决方案。
我的问题是,为什么这是一个无限循环?
不是。堆栈的大小有限。你进行了太多的递归调用,并最终破坏了最大堆栈大小。
我有一种感觉,我错过了一些完全愚蠢的东西。
你来到right place。
答案 1 :(得分:1)
+1给杰森的答案,这清楚地解释了问题。
现在有一些解决方案!我知道至少有三种方法可以从算法中删除递归:
算法是尾递归,如果它的所有递归调用都是尾调用,这意味着它们是在返回之前完成的最后一件事。如果您不清楚,请使用Google查找更好的示例。
通过调整参数和使用goto而不是真实的调用,可以轻松地转换此类算法。再看一下你的例子:
private int Euler5(int dividend, int divisor)
{
tail_call:
if (divisor < 21)
{
// if it equals zero, move to the next divisor
if (dividend % divisor == 0)
{
divisor++;
goto tail_call; // return Eular5(dividend, divisor);
}
else
{
dividend++;
// return Eular5(dividend, 1); // move to the dividend
divisor = 1;
goto tail_call;
}
}
// oh hey, the divisor is above 20, so what's the dividend
return dividend;
}
哦,嘿!它具有完全相同的功能,但具有固定的堆栈大小(没有呼叫,只有跳转)。
现在有人会说:&#34;呃......搞砸了!他们是邪恶的!死了,死了!&#34;。我说这是少数合法用途之一。毕竟,如果您的编译器足够智能,它本身就会进行尾调用优化(F#实际上是这样,C#不会,JIT可能在x64上执行,而不是在x86上执行)。
但对于那些我说的人:看起来好一点。因为每个if / else分支的末尾都有一个goto,所以我可以将它移到&#34; if&#34;完全。现在我有类似&#34; start:if(X){Y();转到开始; }&#34;想一想,它只是一个&#34;而(X)Y()&#34;环。所以你刚刚找到函数的迭代版本:
private int Euler5(int dividend, int divisor)
{
while (divisor < 21)
{
// if it equals zero, move to the next divisor
if (dividend % divisor == 0)
{
divisor++;
}
else
{
dividend++;
divisor = 1;
}
}
// oh hey, the divisor is above 20, so what's the dividend
return dividend;
}
尼斯!