大数阶乘

来源:互联网 发布:下载文件进度条js特效 编辑:程序博客网 时间:2024/06/14 10:46

C/C++语言中,int范围[-2^31,2^31 -1] 即 [-2147483648,2147483647]。
在进行阶乘运算中,12!=479001600,13!=6227020800,也就意味着超过13的阶乘就不能用int型进行存储。对于大数的阶乘,要换一种方式进行存储。
输入一个数值n,首先要估算n!的位数:

int getSize(int n)  //计算结果的大概位数{    int i,j,num;    for(i=1,j=n;j/10>0 || j%10>0;i++)    {        j/=10;    }    //num=n*--i+1;  //此计算式为多次总结归纳得到    num=n*--i/3+1;  //一个int存储的数字的范围为0~9999,按理说是n*--i/4+1,此处多申请一些以防开辟的空间不足    return num;}

通过此函数得到的位数会比实际的位数要多。
得到位数size之后,申请一个长度为size的int型数组,初始化末位为1,其余全为0;
然后从末位起倒着乘以每一个数,将数组中每一个数字的范围为0~9999,超过范围的数字向前进位。最后将结果通过string字符串返回。代码如下:

string factorial(int n){    string outp;    int *temparr,num;    int getSize(int n);    int getNumLength(int n);    int i,j,k;    int wsize=10000;    int size=getNumLength(wsize)-1;    num=getSize(n);    temparr=new int [num];    for(i=0;i<num;i++)    {        if(i==num-1) temparr[i]=1;        else temparr[i]=0;    }    if(n==0) temparr[num-1]=1;    else    {        for(i=1;i<=n;i++)        {            int count=num-getSize(i)-1;            for(j=num-1;j>=count && j-1>=count;j--)                temparr[j]*=i;            for(k=num-1;k>=count && k-1>=count;k--)            {                if(temparr[k]>wsize)                 {                    temparr[k-1]+=(temparr[k]/wsize);                    temparr[k]=(temparr[k]%wsize);                }                else continue;            }        }    }    int midd=0;    for(i=0;i<num;i++)    {        if(temparr[i]==0) midd+=1;        else break;    }    char s[8];    sprintf(s,"%d",temparr[midd]);   //从第midd位开始为非0数    outp+=s;    for(i=midd+1;i<num;i++)    {        sprintf(s,"%04d",temparr[i]);   //四位有效数字,不足的情况用0填充        outp+=s;    }    if(temparr)    {        delete [] temparr;        temparr=NULL;    }    return outp;}

其中,int getNumLength(int n)函数的实现代码为:

int getNumLength(int n){    if(n==0) return 1;    else if(n<0) return -1;    int size=0;    while(n)    {        n/=10;        ++size;    }    return size;}

main函数中:

int main(int argc, char* argv[]){    int getSize(int n);    int getNumLength(int n);    string factorial(int n);    cout<<"//------------------------------大数阶乘------------------------------//"<<endl;    cout<<"//--------- 数组求阶乘,为方便运算,原则不大于100000,否则会很慢 --------//"<<endl;    int n;    cin>>n;    string s;    double timebegin=(double)clock()/CLOCKS_PER_SEC;    if(n<0)     {        cout<<"输入有误!!!"<<endl;        return 0;    }    else    {        s=factorial(n);        cout<<n<<"!=";        cout<<s<<endl;        if(n>=30)   //启用科学计数法        {            cout<<n<<"!="<<s[0]<<".";            for(int i=1;i<20;++i)                cout<<s[i];            cout<<"e+"<<s.size()-1<<endl;        }    }    printf("time: %.6f\n\n",(double)clock()/CLOCKS_PER_SEC-timebegin);    system("pause");    return 0;}

运行结果:

20的阶乘:
这里写图片描述

1000的阶乘:
这里写图片描述

20000的阶乘:(此时的时间包括输出的时间,输入到输出结果光标闪动4次左右)
这里写图片描述

希望对大家有帮助。

0 0
原创粉丝点击