高精度计算-n的阶乘

时间:2021-02-01 03:37:22
问题描述
  输入一个正整数n,输出n!的值。
  其中n!=1*2*3*…*n。
算法描述
  n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。
  将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
  首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。
输入格式
  输入包含一个正整数n,n<=1000。
输出格式
  输出n!的准确值。
样例输入
10
样例输出
3628800

n的阶乘是不难,但是关键在于n取值太大,数据会溢出,不能用数据类型存储,所以只能把数据存在字符数组里面,再对字符数组进行

乘法运算,本来想到java的大数类可以直接解决这问题,但是感觉那样没有意义。解决问题的时候碰到点小插曲,至今还没有明白为什么

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void calculate_mul(char *mul_1,char *mul_2,char *result)//两个字符数的乘法
{
    int i,j,k=0,off=-1,r=0;
    int temp0;
    for(i=strlen(mul_2)-1;i>=0;i--)
    {
        r=0;
        off++;
        k=0;
        for(j=strlen(mul_1)-1;j>=0;j--)
        {
           if(result[k+off]==0)
            {
                result[k+off]=((mul_1[j]-'0')*(mul_2[i]-'0')+r)%10+'0';
                r=((mul_1[j]-'0')*(mul_2[i]-'0')+r)/10;
            }
            else
            {
                 temp0=result[k+off]-'0';
                 result[k+off]=(result[k+off]-'0'+(mul_1[j]-'0')*(mul_2[i]-'0')+r)%10+'0';
                 r=(temp0+(mul_1[j]-'0')*(mul_2[i]-'0')+r)/10;
            }
            k++;
        }
        if(r!=0)
        {
            result[k+off]='0'+r;
        }
    }
    strrev(result);
}
void nn(char *str_nn)
{
    int i,n;
    char r[3000]="1";
    char tmp[3000]="1";
    char tmp2[3000]="1";
    n=atoi(str_nn);
    for(i=1;i<=n;i++)
    {
        strcpy(tmp,r);
        strcpy(r,"0");
        strcpy(tmp2,"0");
        itoa(i,tmp2,10);
        calculate_mul(tmp,tmp2,r);
    }
    printf("%s\n",r);
}
int main()
{
    char str_n[10]={0};
    scanf("%s",&str_n);
    nn(str_n);
    return 0;
}

n<=7的时候都正确,但是n=8的时候,却出乎意料的输出了40720,8!=7!*8=5040*8=40320,调试半天还是没有调试看出问题所在。

第二天各种尝试改成下面,竟然成功了。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void calculate_mul(char *mul_1,char *mul_2,char *result)//两个字符数的乘法
{
    int i,j,k=0,off=-1,r=0;
    int temp0;
    for(i=strlen(mul_2)-1;i>=0;i--)
    {
        r=0;
        off++;
        k=0;
        for(j=strlen(mul_1)-1;j>=0;j--)
        {
           if(result[k+off]==0)
            {
                result[k+off]=((mul_1[j]-'0')*(mul_2[i]-'0')+r)%10+'0';
                r=((mul_1[j]-'0')*(mul_2[i]-'0')+r)/10;
            }
            else
            {
                 temp0=result[k+off]-'0';
                 result[k+off]=(result[k+off]-'0'+(mul_1[j]-'0')*(mul_2[i]-'0')+r)%10+'0';
                 r=(temp0+(mul_1[j]-'0')*(mul_2[i]-'0')+r)/10;
            }
            k++;
        }
        if(r!=0)
        {
            result[k+off]='0'+r;
        }
    }
    strrev(result);
}
void nn(char *str_nn)
{
    int i,n;
    char r[3000]="1";
    char tmp[3000]="1";
    char tmp2[3000]="1";
    n=atoi(str_nn);
    for(i=1;i<=n;i++)
    {
         memset(tmp,0,sizeof(tmp));
        strcpy(tmp,r);
        memset(r,0,sizeof(r));
        memset(tmp2,0,sizeof(tmp2));
        itoa(i,tmp2,10);
        calculate_mul(tmp,tmp2,r);
    }
    printf("%s\n",r);
}
int main()
{
    char str_n[10]={0};
    scanf("%s",&str_n);
    nn(str_n);
    return 0;
}