【问题标题】:recursive function error: "stack overflow"递归函数错误:“堆栈溢出”
【发布时间】:2011-07-12 02:39:26
【问题描述】:

我编写了这个函数,它应该找到可以被每个数字 1 到 20 整除的最小正整数。我得到“堆栈溢出错误”,尽管当我测试数字 1 到 10 时,它工作得很好。 这是我的代码:

#include<iostream>
#include<cstdlib>

using namespace std;

// function prototype
int smallPos(int k, int m,int n);

int main(){
    printf("the smallest positive number that is divisible by 1 through 20 is %d ", smallPos(1,1,13));

}

int smallPos(int k, int n, int m){
    int div=0;
    for(int i = n;i<=m;i++) {
        if (k%i==0) 
            div++;
    } 
    if (div==m) {
        return k;
    } else {
        k+=1;
        smallPos(k,n,m);
    }   
}

为什么会这样?无论如何,这个数字不应该那么大。 谢谢!

【问题讨论】:

  • 为什么这甚至被实现为递归函数?
  • 这是我能想到的解决方案。我尝试使用嵌套循环但感到困惑。
  • 您可以在第一次失败时为自己节省一些循环和递归:for(int i = n; i &lt;= m; i++) if(k % i) return smallPos(k + 1, n, m); return k; 但堆栈溢出仍然存在。
  • 有人在做欧拉项目
  • @GKED:用可行的解决方案更新了我的答案。

标签: c++ recursion


【解决方案1】:

最终条件 (div == m) 永远不会为真。要使div 等于m,数字k 应该能被[n,m) 范围内的所有数字整除。

编辑:我重读了printf() 调用中的文本以了解该函数的作用。您正在寻找可被范围内所有数字整除的第一个数字。如果我的计算是正确的,这个数字应该是该范围内数字的所有唯一素数的乘积。对于[1,13] 范围(根据函数调用,而不是文本),此数字应为:

30030 = 1 * 2 * 3 * 5 * 7 * 9 * 11 * 13

现在,这意味着您将递归调用该函数超过 30,000 次,对于您正在使用的堆栈大小而言,这显然是太多次了(默认值相对较小)。对于这个大小的范围,你真的应该考虑编写一个迭代函数。

编辑:这是一个似乎可行的迭代版本。

int smallPos ( int n, int m )
{
    int k = 0;
    while ( ++k )
    {
        int count = 0;
        for (int i = n; i<=m; i++)
        {
            if (k%i==0) {
                ++count;
            }
        }
        if (count == (m-n+1)) {
            return k;
        }
    }
    return k;
}

确实,smallPos(1,10) 的结果是 2520。看来我之前的估计是一个下限,而不是一个固定的结果。

【讨论】:

  • 这对于很多人来说都是正确的,我还没有弄清楚:)。例如,对于所有 i 1:10 可整除的最小正整数是 2520。
  • 不应该是1890(1 * 2 * 3 * 5 * 7 * 9)吗?
  • 我认为你是对的,我应该尝试找出迭代的方式。
  • 无论如何,你都需要增加m,因为能被所有[n,m]整除的最小数必然大于m
【解决方案2】:

您的smallPos 函数会导致未定义的行为,因为它没有在所有执行路径中返回值。你可能想在最后一部分说return smallPos(k,n,m);(或者直接说return smallPos(k + 1, n, m);)。

【讨论】:

  • 虽然这是真的,但这不是导致堆栈溢出的原因。
  • @Andy:你说得对,OP 的功能实际上永远不会在当前版本中返回......无论如何,我的 UB 总有一天会击败你的逻辑推理;-)
  • 哈哈哈!如果你把 UB 赌在逻辑推理上,你就没有推理,我只会让你认为你赢了:-)
猜你喜欢
  • 2017-09-05
  • 2019-08-25
  • 2018-03-10
  • 2014-08-27
  • 2016-11-11
  • 2017-06-18
  • 2017-10-20
  • 2015-06-17
相关资源
最近更新 更多