【问题标题】:Recursion with Max Integer最大整数递归
【发布时间】:2014-06-05 06:57:48
【问题描述】:

我正在编写一个程序来计算一个数字的阶乘。我正在使用递归来解决这个问题。我遇到的问题是,一旦我达到 13 号,由于 INT 的限制,它会抛出垃圾号。我想要做的是实现一种在错误发生时捕获错误的方法(没有硬线在 x=13 它必须停止,而是通过输出)。这是我的尝试:

#include <stdio.h>

int factorial( int n)
{
    printf("Processing factorial( %d )\n", n);

    if (n <= 1)
    {
        printf("Reached base case, returning...\n");
        return 1;
    }
    else
    {
        int counter = n * factorial(n-1);       //Recursion to multiply the lesser numbers

        printf("Receiving results of factorial( %d ) =  %d * %d! = %d\n", n, n, (n-1), counter);

        if( counter/n != factorial(n-2) ) //my attempt at catching the wrong output
        {
            printf("This factorial is too high for this program ");
            return factorial(n-1);
        }
        return counter;


        printf("Doing recursion by calling factorial (%d -1)\n", n);
    }


}


int main()
{
    factorial(15);
}

问题在于程序现在永远不会终止。它不断循环并向我抛出随机结果。

由于我无法回答自己的问题,我将使用我的解决方案进行编辑:

int jFactorial(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    else
    {
        int counter = n *jFactorial(n-1);
        return counter;
    }
}

void check( int n)
{
    int x = 1;
    for(x = 1; x < n+1; x++)
    {
        int result = jFactorial(x);
        int prev = jFactorial(x-1);
        if (((result/x) != prev) || result == 0 )
        {
            printf("The number %d makes function overflow \n", x);
        }
        else
        {
            printf("Result for %d is %d \n", x, result);
        }
    }
}

【问题讨论】:

  • 为什么counter / n 永远等于factorial(n-2)?别介意添加一个额外的递归案例有点问题,你的数学是错误的。
  • @hobbs 我正在尝试检查阶乘(N)/N 是否不等于前一个数字的阶乘,因为这会告诉我输出是否正确。
  • 是的,我明白了。
  • “前一个号码”不是factorial(n-2),而是factorial(n-1)
  • 我认为您知道,与简单地计算 2..n 的乘积相比,递归是计算阶乘的不好方法。

标签: c ansi factorial


【解决方案1】:

更好的方法:

if (n <= 1) {
   return 1;
} else {
    int prev_fact = factorial(n - 1);
    if (INT_MAX / prev_fact < n) { /* prev_fact * n will overflow */
        printf("Result too big");
        return prev_fact;
    } else {
        return prev_fact * n;
    }
}

使用更准确的检查(我希望)来检查乘法是否会溢出,并且不再向factorial 添加任何调用。

【讨论】:

  • 如何定义 int_max?我尝试了#define MAXIMUM INT_MAX,但它不起作用
  • 我认为这行不通。我们以 3 为例。 MAX_INT 为 4.1b,除以前一个阶乘(2),结果为 2。那么 4.1b/2 大于 n,即 3,会输出结果太大。看看我的编辑,我可以用两种方法解决它,现在我正在尝试将这两种方法合并为 1。
  • @hobbs 认为你想要if (MAX_INT / prev_fact &lt; n) {&lt;&gt;.
  • @user3708229 #include &lt;limits.h&gt;
  • @user3708229 并查看我所做的 chux 建议的更改,&lt; 而不是 &gt;
【解决方案2】:

更新

仔细观察后发现我错过了gmp也为C实现的事实。这是C中的解决方案

我已经能够在我的 macbook pro 上运行它,使用自制软件安装 gmp (brew isntall gmp)

#include <gmp.h>

#include <stdio.h>

void factorial(mpz_t ret, unsigned n) {
  if (n <= 1) {
    mpz_set_ui(ret, 1);//Set the value to 1
  } else {
    //multiply (n-1)! with n
    mpz_t ret_intermediate;
    mpz_init (ret_intermediate);//Initializes to zero
    factorial(ret_intermediate, n-1);
    mpz_mul_ui(ret, ret_intermediate, n);
  }

  return;
}

int main(){
  mpz_t result;
  mpz_init (result);
  factorial(result, 100);
  char * str_result = mpz_get_str(NULL, 10, result);
  printf("%s\n", str_result);
  return 0;
}

原答案

快速谷歌搜索后,我找到了以下解决方案。请注意,这是一个 C++ 解决方案。我在底部简要描述了如何在 ANSI C 中做同样的事情。

Big numbers library in c++

https://gmplib.org/这个 c++ 库可以处理任意大的数字。

结帐https://gmplib.org/manual/C_002b_002b-Interface-General.html

整个代码可能看起来像......

#include <gmpxx.h>

#include <iostream>

mpz_class factorial(unsigned n) {
  if (n <= 1) return mpz_class(1);

  return mpz_class(n) * factorial(n-1);
}

int main(){
  mpz_class result = factorial(100);
  std::string str_result = result.get_str();
  std::cout << str_result << std::endl;
  return 0;
}

ANSI C 版本

您可以使用 ansi C 实现同样的事情,其结构可以容纳扩展的数字列表(使用链表或任何其他可扩展的数组列表容器),您只需要实现三个方法...初始化,相乘并转换为字符串。

【讨论】:

  • 但是如果结果溢出就行不通了。而且它看起来不像 ANSI C
  • 是的,你是对的,这是 C++ 解决方案。使用阶乘之类的东西,您必须手动实现像mpz_class 这样的大数字类。这实际上是可行的。
  • @user3708229 我已经添加了一个关于将其适应 ANSI C 的简要指南。如果仍有任何混淆,请告诉我。
  • 检查我的编辑并告诉我您是否认为它比您的解决方案更好
  • @user3708229 这个答案在程序完全耗尽内存之前不会溢出。
猜你喜欢
  • 2023-04-07
  • 2010-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
相关资源
最近更新 更多