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

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

两边n>=Log101+Log102+Log10 3+....Log10 n
这样n!的位数肯定等于小于Log101+Log102+Log10 3+....Log10 n.

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

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


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

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

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

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

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

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

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

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

206        }

207        bit++;
208        
209    }

210    fprintf(fp,"\n");
211    fclose(fp);
212}

213
好了,不说了.
下载代码
Last Updated: 2005年7月14日12:43:07 感谢kwklover 的建议
Last Updated: 2005年7月15日 8:48:20 感谢arbean.wu的精彩建议
Last Updated:2006年4月21日
posted @ 2005-07-14 12:17  张太国  阅读(25031)  评论(36编辑  收藏  举报