【问题标题】:Segmentation fault for numbers too big for Ackermann's function对于 Ackermann 函数而言,数字太大的分段错误
【发布时间】:2020-12-29 13:41:00
【问题描述】:

为什么会失败?我用 C 语言编写了 Ackermann 的函数,并使用 long 来确保数字不会太小。然而,当我为 m 和 n 超过(包括)4 时,它给了我一个segmentation fault: 11。有谁知道为什么?

  #include <stdio.h>

  int ackermann(long m, long n) {
      if (m == 0)
              return n + 1;
      else if (m > 0 && n == 0)
              return ackermann(m - 1, 1);
      else if (m > 0 && n > 0)
              return ackermann(m - 1, ackermann(m, n - 1));
  }

  int main() {
          long result = ackermann(4, 4);
          printf("%lu", result);
  }

【问题讨论】:

  • 在许多系统上long 的大小与int 相同。试试long longint64_t
  • en.wikipedia.org/wiki/Ackermann_function#Table_of_values。 Ackermann(4, 4) 是一个数以千计的数字。没有任何 C 类型可以接近存储该数字。
  • 分段错误...现在“堆栈溢出”的名称从何而来...

标签: c recursion segmentation-fault long-integer ackermann


【解决方案1】:

我用 C 语言编写了 Ackermann 的函数并使用 long 来确保 没有数字会太小。

unsigned long long 的大小为 2^6 (64) 位。 ackermann(4, 2) 的结果大小大于 2^16 (65536) 位。您可以计算ackermann(4, 1)ackermann(5, 0),但mn 的值较大。

代码方面,当 unsigned long 可能为您提供更好的服务时,您使用 signed long,并且您声明 ackermann() 函数本身返回一个signed int 不一致。 (您的 ackermann() 函数还有第四个退出点,但在编译器方面没有正确定义。)这是使用 unsigned long long 对您的代码进行的返工,但仍然不会让您走得太远:

#include <stdio.h>

unsigned long long ackermann(unsigned long long m, unsigned long long n) {
    if (m == 0) {
        return n + 1;
    }

    if (m > 0 && n == 0) {
        return ackermann(m - 1, 1);
    }

    return ackermann(m - 1, ackermann(m, n - 1));
}

int main() {
    unsigned long long result = ackermann(5, 0);
    printf("%llu\n", result);

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-29
    • 2016-03-11
    • 1970-01-01
    • 2021-05-27
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多