【问题标题】:Segmentation fault in a recursive approach to compute factorial(n)%m计算阶乘(n)%m 的递归方法中的分段错误
【发布时间】:2014-10-30 22:18:41
【问题描述】:

我正在尝试使用C 中的递归计算n! % m。这是我正在使用的code

#include<stdio.h>
#define m 1000000007

long long int fact(long long int n) {
    if(n == 1)
        return (1);
    long long int n2 = (long long int)(fact(n-1));
    long long int k = (n*n2)%m;
    return k;
}

int main() {
    printf("%lld",fact(1000000));
}

这个程序给出 SEGMENTATION FAULT ,但是如果我用迭代方法替换 fact 函数,那么程序会打印正确的答案。迭代 fact 函数是

long long int fact(long long int n){
    long long int k =1;
    long long int i;
    for(i = n;i>1;i--)
        k = (k*i)%m;
    return k; 
}

那么为什么迭代方法有效但递归方法失败了?

【问题讨论】:

  • 看起来你正在溢出调用堆栈。尝试使用ulimit -s unlimited 来增加堆栈大小。
  • 你的调用栈的最大高度小于你的long long int i的最大值。

标签: c recursion factorial


【解决方案1】:

尝试 gdb,但可能是因为您已达到最大递归深度,换句话说,无论是字面意思还是基于您的操作系统的当前规则集,“内存”都用完了。

【讨论】:

    【解决方案2】:

    如果您的 C 编译器优化了尾调用,您可以将递归函数重写为尾递归函数:

    long long int fact_aux(long long int n, long long int acc) {
        if(n <= 1)
            return acc;
        return fact_aux(n-1, (n * acc)%m);
    }
    
    long long int fact(long long int n) {
         return fact_aux(n, 1);
    }
    

    请注意,C 标准不需要 TCO,因此您无法保证它会像循环一样有效。 GCC does it.

    【讨论】:

      猜你喜欢
      • 2019-05-26
      • 1970-01-01
      • 2015-04-19
      • 1970-01-01
      • 2013-09-18
      • 1970-01-01
      • 2017-04-19
      • 1970-01-01
      • 2021-01-22
      相关资源
      最近更新 更多