程序不会返回大输入值的输出,例如50.它返回0.这是一个使用递归的阶乘程序

时间:2016-05-23 17:56:31

标签: c

/*Program to find factorial of a number using recursion*/ 

#include<stdio.h>
#include<stdlib.h>
/*Function to recursively compute factorial of a number*/
long int fact(long int n)
{
    if(n==0)
    return 1;
    return n*fact(n-1);
}
int main()
{
    long  int n;
    printf(" enter n ");
    scanf("%ld",&n);
    printf ("%ld",fact(n));  
    return 0;
}

4 个答案:

答案 0 :(得分:1)

50!30414093201713378043612608166064768844377641568960512000000000000或约为3.04e+64,为215位数。此值通常超出long等类型的范围。即使uintmax_tunsigned long long只需要能够表示至少64位整数。

long int fact(long int n) {
  ...
  // Overflows!
  return n*fact(n-1);

要获得确切的答案,代码可以使用其他类型。以下使用整数的字符串/十进制表示。它适用于n的大值,因为正确的功能受缓冲区大小的限制。

char *strfact_mult(char *s, unsigned x) {
  unsigned sum = 0;
  size_t len = strlen(s);
  size_t i = len;
  while (i > 0) {
    sum += (s[--i] - '0')*x;
    s[i] = sum%10 + '0';
    sum /= 10;
  }
  while (sum) {
    len++;
    memmove(&s[1], s, len);
    s[i] = sum%10 + '0';
    sum /= 10;
  }
  return s;
}

char *str_fact(char *dest, unsigned n) {
  strcpy(dest, "1");
  while (n > 1) {
    strfact_mult(dest, n--);
  }
  return dest;
}

int main(void) {
  char buf[1000];
  puts(str_fact(buf, 0));
  puts(str_fact(buf, 1));
  puts(str_fact(buf, 5));
  puts(str_fact(buf, 50));
}

输出

1
1
120
30414093201713378043612608166064768844377641568960512000000000000

答案 1 :(得分:0)

50!是一个非常大的数字(超过60位数),2^64小于50!。您没有获得正确号码的原因是您得到overflow,您的数量超出了计算机可以计算的数量限制。

enter n 50
-3258495067890909184

如果你有一个64位整数,它可以代表的最大值是2 ^ 64,我小于50!因此你会溢出。

通常在这些情况下,你会采用一些技巧,类似于运行8位代码的4位系统,方法是将每个字的指令数加倍(Intels first CPU具有8位代码的方式)。

因此,您的64位系统实际上可以处理128位字,您只需要编写一个算法,将数据放入&#34;块&#34;这样你就可以加倍你的单词长度。

答案 2 :(得分:0)

它不适用于标准C类型,您需要其他东西(可能是字符串)。请查看http://onlinemschool.com/math/formula/factorial_table/

正如你所看到的,这是一个非常大的数字。

答案 3 :(得分:0)

/* program to calculate large factorials with exact precision

   original program by chux, modified by ringzero
*/

#include <stdio.h>
#include <string.h>

char *strfact_mult(char *s, unsigned x)
{
    // modified code starts
    int len = strlen (s);
    int carry = 0;

    for ( int i = 1; i <= len; ++i ) {
        int product = (s[len - i] - '0') * x + carry;
        s[len - i] = product % 10 + '0';
        carry = 0;
        if ( product > 9 ) {
            carry = product / 10;
            if ( i == len ) {
                ++len;
                memmove (&s[1], s, len);
                s[0] = '0';
            }
        }
    }
    // modified code ends

    //unsigned sum = 0;
    //size_t len = strlen(s);
    //size_t i = len;
    //while (i > 0) {
    //  sum += (s[--i] - '0')*x;
    //  s[i] = sum%10 + '0';
    //  sum /= 10;
    //}
    //while (sum) {
    //  len++;
    //  memmove(&s[1], s, len);
    //  s[i] = sum%10 + '0';
    //  sum /= 10;
    //}

    return s;
}

char *str_fact(char *dest, unsigned n)
{
    strcpy(dest, "1");
    while (n > 1) {
      strfact_mult(dest, n--);
    }
    return dest;
}

int main (void)
{
    char buf[1000];
    puts(str_fact(buf, 0));
    puts(str_fact(buf, 1));
    puts(str_fact(buf, 5));
    puts(str_fact(buf, 50));
}