10000的阶乘的算法(大数的阶乘)

   很多天没有更新自己的Blog了,前几天拿到一个题目.就是写一段程序计算10000的阶乘.当时我还以为这题目非常简单,没想到还是需要动点大脑的.花了将近半个小时才搞定,拿出来分享一下. 
   为什么不能用普通的方法来写呢,比如说递归?在我的教科书上可是用的是递归呀?不知道你注意没有,如果是100的阶乘的话,其结果肯定是非常大的,以我们现有语言的数据类型肯定是没法使用的,就拿C来说,long型能存的下100的阶乘吗?未必.所以我就使用数组来存储结果的每一位,然后输出每一位不就是结果吗.
  那么具体怎样去做?
  首先确定结果的位数?如何确定呢?请看下面.
  2!=1*2<=10*10
  3!=1*2*3<=10*10*10
.......
所以我们可以得出一个结论
          n!<=10
n
所以n!的位数可以这样计算:
两边取对数,即log 10n!<=log 10 10n

两边n>=Log 101+Log 102+Log 10 3+....Log 10 n
这样n!的位数肯定等于小于Log 101+Log 102+Log 10 3+....Log 10 n.

以上是错误的
正确的推断如下:

可以将n!表示成10的次幂,即n!=10^M(10的M次方)则不小于M的最小整数就是 n!的位数,
对该式两边取对数,有=log10^n!即:
M = log10^1+log10^2+log10^3...+log10^n
循环求和,就能算得M值,该M是n!的精确位数。


位数的确定解决之后,就看看如何计算了.
看看如下代码:

 1 None.gif int  index = 0 ;
 2 None.gif     long  carrier = 0 ;
 3 None.gif     double  bitCount  =   1
 4 None.gif     int  begin  =   0
 5 None.gif  
 6 None.gif     for (index = 2 ; index <= n;  ++ index) 
 7 ExpandedBlockStart.gifContractedBlock.gif     dot.gif
 8InBlock.gif        long multiValue = 0;   
 9InBlock.gif        bitCount += log10((long double)index); 
10InBlock.gif        if(arrValue[begin] == 0
11InBlock.gif            begin++
12InBlock.gif  
13InBlock.gif        for(int j=begin; j<int(bitCount); ++j) 
14ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif
15InBlock.gif            multiValue += (index*arrValue[j]); 
16InBlock.gif            arrValue[j] = char(multiValue % 10); 
17InBlock.gif            multiValue /= 10
18ExpandedSubBlockEnd.gif        }
 
19ExpandedBlockEnd.gif    }
 

这里就是计算的关键了.注意一下进位问题即可.所有代码如下:

  1 None.gif
  2 ExpandedBlockStart.gifContractedBlock.gif /**/ //
  3 None.gif //       Date created:    2005/07/12
  4 None.gif //      Author:        Confach Zhang
  5 None.gif //      Purpose:         计算n!的值
  6 ExpandedBlockStart.gifContractedBlock.gif /**/ //
  7 None.gif
  8 None.gif  
  9 None.gif using   namespace  std; 
 10 None.gif#include  " StdAfx.h "
 11 None.gif#include  < iostream.h >
 12 None.gif#include  < conio.h >
 13 None.gif#include  < stdlib.h >
 14 None.gif#include  < math.h >
 15 None.gif#include  < stdio.h >
 16 None.gif#include  < iomanip.h >
 17 None.gif  
 18 None.gif int  GetNumber();                                    // 输入 n 
 19 None.gif int  GetBitLength( int  n);                            // 求n!的位数
 20 None.gif char *  Initialize( int );                              // 初始化存储结果的值
 21 None.gif void  PrintValue( char   * a, int  size);                  // 打印值到屏幕
 22 None.gif void  PrintValue( char   * a, int  size, char *  fileName);   // 打印值到文件
 23 None.gif char *  GetValue( int  val);                            // 计算
 24 None.gif char *  SubGetValue( char *  , int );                      
 25 None.gif
 26 None.gif
 27 None.gif int  main() 
 28 ExpandedBlockStart.gifContractedBlock.gif dot.gif
 29InBlock.gif    int value=GetNumber();
 30InBlock.gif    char fileName[16];
 31InBlock.gif    int size=GetBitLength(value);
 32InBlock.gif    char *pa = Initialize(size);
 33InBlock.gif
 34InBlock.gif    //pa=GetValue();
 35InBlock.gif    pa=GetValue(value);
 36InBlock.gif
 37InBlock.gif    PrintValue(pa,size); 
 38InBlock.gif
 39InBlock.gif    //sprintf(fileName,"%s","10000!.txt");
 40InBlock.gif    sprintf(fileName,"%d!.txt",value);
 41InBlock.gif    
 42InBlock.gif    PrintValue(pa,size,fileName);
 43InBlock.gif    delete []pa;  //note: 
 44InBlock.gif    return 1;
 45ExpandedBlockEnd.gif}
 
 46 None.gif // 函数GetValue
 47 None.gif //  求得计算结果
 48 None.gif // 返回结果
 49 None.gif // History:
 50 None.gif // 1)char* GetValue()
 51 None.gif // 2)GetValue(int val)
 52 None.gif //   参数:val 计算阶乘的值
 53 None.gif char *  GetValue( int  val)
 54 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 55InBlock.gif    //定义一个数组存储阶乘的值
 56InBlock.gif    //首先得到10000!阶乘的位数
 57InBlock.gif    int VALUE=val; 
 58InBlock.gif    int length=GetBitLength(VALUE);
 59InBlock.gif    char *arrValue = new char[length]; 
 60ExpandedSubBlockStart.gifContractedSubBlock.gif    if(!arrValue) dot.gif{
 61InBlock.gif        cout <<"申请内存失败!" << endl; 
 62InBlock.gif        exit(1); 
 63ExpandedSubBlockEnd.gif    }
 
 64InBlock.gif    arrValue[0= 1
 65InBlock.gif    for(int i=1; i<length; i++
 66InBlock.gif        arrValue[i] = 0
 67InBlock.gif    arrValue=SubGetValue(arrValue,VALUE);
 68InBlock.gif    return arrValue;
 69ExpandedBlockEnd.gif}

 70 None.gif
 71 None.gif char *  SubGetValue( char *  arrValue, int  n)
 72 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 73InBlock.gif    int index=0;
 74InBlock.gif    long carrier=0;
 75InBlock.gif    double bitCount = 1
 76InBlock.gif    int begin = 0
 77InBlock.gif  
 78InBlock.gif    for(index=2; index<=n; ++index) 
 79ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif
 80InBlock.gif        long multiValue = 0;   
 81InBlock.gif        bitCount += log10((long double)index); 
 82InBlock.gif        if(arrValue[begin] == 0
 83InBlock.gif            begin++
 84InBlock.gif  
 85InBlock.gif        for(int j=begin; j<int(bitCount); ++j) 
 86ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif
 87InBlock.gif            multiValue += (index*arrValue[j]); 
 88InBlock.gif            arrValue[j] = char(multiValue % 10); 
 89InBlock.gif            multiValue /= 10
 90ExpandedSubBlockEnd.gif        }
 
 91ExpandedSubBlockEnd.gif    }
 
 92InBlock.gif  return arrValue;
 93ExpandedBlockEnd.gif}

 94 None.gif
 95 None.gif // 得到计算阶乘的值,此函数为新增
 96 None.gif int  GetNumber() 
 97 ExpandedBlockStart.gifContractedBlock.gif dot.gif
 98InBlock.gif    int n; 
 99InBlock.gif    cout << "请输入要计算阶乘的n值: "
100InBlock.gif    cin >> n; 
101ExpandedSubBlockStart.gifContractedSubBlock.gif    while(n < 0dot.gif
102InBlock.gif        cout << "输入错误,请重新输入: "
103InBlock.gif        cin >> n; 
104ExpandedSubBlockEnd.gif    }
 
105InBlock.gif    if(n == 0
106InBlock.gif        exit(1); 
107InBlock.gif    return n; 
108ExpandedBlockEnd.gif}
 
109 None.gif
110 None.gif // 函数GetBitLength
111 None.gif //  求得计算结果的位数,本函数为新增加
112 None.gif // 参数
113 None.gif //      n 需要计算的阶乘的数
114 None.gif // 返回结果的位数
115 None.gif int  GetBitLength( int  n) 
116 ExpandedBlockStart.gifContractedBlock.gif dot.gif
117InBlock.gif    double sum = 1.0
118InBlock.gif    for(int i=1; i<=n; i++
119InBlock.gif        sum += log10((long double)i);
120InBlock.gif    return int(sum); 
121ExpandedBlockEnd.gif}
 
122 None.gif // -----------
123 None.gif // 函数:Initialize
124 None.gif //    初始化存储结果的数组
125 None.gif // 参数:
126 None.gif //      size      数组的长度  
127 None.gif // 返回值
128 None.gif //     初始化后的数组
129 None.gif // -------------
130 None.gif char   *  Initialize( int  size) 
131 ExpandedBlockStart.gifContractedBlock.gif dot.gif
132InBlock.gif    char *arrValue = new char[size];
133ExpandedSubBlockStart.gifContractedSubBlock.gif    if(!arrValue) dot.gif{
134InBlock.gif        cout << size<<"太大,申请内存失败!" << endl; 
135InBlock.gif        exit(1); 
136ExpandedSubBlockEnd.gif    }
 
137InBlock.gif    arrValue[0= 1
138InBlock.gif    for(int i=1; i<size; i++
139InBlock.gif        arrValue[i] = 0
140InBlock.gif    return arrValue; 
141ExpandedBlockEnd.gif}
 
142 None.gif  
143 None.gif // -----------
144 None.gif // 函数:PrintValue
145 None.gif //    将结果输入到屏幕上
146 None.gif // 参数:
147 None.gif //      buff      存储结果的数组
148 None.gif //    buffLen   数组的长度
149 None.gif //    fileName  文件名         
150 None.gif // -------------
151 None.gif void  PrintValue( char   * buff,  int  buffLen) 
152 ExpandedBlockStart.gifContractedBlock.gif dot.gif
153InBlock.gif    int bit = 0
154InBlock.gif    int nCol=0;
155ExpandedSubBlockStart.gifContractedSubBlock.gif    for(int i=buffLen-1; i>=0; i--dot.gif
156InBlock.gif        if(bit % 10 == 0
157ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
158InBlock.gif            cout << " " ; 
159InBlock.gif            nCol++;
160InBlock.gif            if(nCol==10)cout<<endl;
161ExpandedSubBlockEnd.gif        }

162InBlock.gif          cout << int (buff[i]);   
163InBlock.gif        bit++
164ExpandedSubBlockEnd.gif    }
 
165InBlock.gif    cout << endl; 
166InBlock.gif    
167ExpandedBlockEnd.gif}
 
168 None.gif // -----------
169 None.gif // 函数:PrintValue
170 None.gif //    将结果输入到一个文件中
171 None.gif // 参数:
172 None.gif //      buff      存储结果的数组
173 None.gif //    buffLen   数组的长度
174 None.gif //    fileName  文件名         
175 None.gif // -------------
176 None.gif
177 None.gif void  PrintValue( char   * buff, int  buffLen, char   * fileName)
178 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
179InBlock.gif     int bit = 0
180InBlock.gif    int nCol=0;
181InBlock.gif
182InBlock.gif    FILE *fp=NULL;
183InBlock.gif    //-----------------------------
184InBlock.gif
185InBlock.gif    if (fileName==NULL)        return ;
186InBlock.gif    fp=fopen(fileName,"wt");
187InBlock.gif    if (fp==NULL)
188ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
189InBlock.gif        printf("不能创建文件%s",fileName);
190InBlock.gif        return ;
191ExpandedSubBlockEnd.gif    }

192InBlock.gif
193InBlock.gif    for(int i=buffLen-1; i>=0; i--)
194ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
195InBlock.gif        fprintf(fp,"%d",int(buff[i]));
196InBlock.gif        
197InBlock.gif         if(bit % 9 == 0
198ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
199InBlock.gif            fprintf(fp,"%s"," "); 
200InBlock.gif            nCol++;
201InBlock.gif            if(nCol==8)
202ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
203InBlock.gif                fprintf(fp,"%s","\n");
204InBlock.gif                nCol=0;
205ExpandedSubBlockEnd.gif            }

206ExpandedSubBlockEnd.gif        }

207InBlock.gif        bit++;
208InBlock.gif        
209ExpandedSubBlockEnd.gif    }

210InBlock.gif    fprintf(fp,"\n");
211InBlock.gif    fclose(fp);
212ExpandedBlockEnd.gif}

213 None.gif
好了,不说了.
下载代码
Last Updated: 2005年7月14日12:43:07 感谢 kwklover 的建议
Last Updated: 2005年7月15日 8:48:20 感谢 arbean.wu的精彩建议
Last Updated:2006年4月21日

转载于:https://www.cnblogs.com/confach/archive/2005/07/14/192703.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值