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

出自http://confach.cnblogs.com/archive/2005/07/14/192703.aspx

为什么不能用普通的方法来写呢,比如说递归?在我的教科书上可是用的是递归呀?不知道你注意没有,如果是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 int  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   
  9 using   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   
 18 int  GetNumber();                                    // 输入 n 
 19 int  GetBitLength( int  n);                            // 求n!的位数
 20 char *  Initialize( int );                              // 初始化存储结果的值
 21 void  PrintValue( char   * a, int  size);                  // 打印值到屏幕
 22 void  PrintValue( char   * a, int  size, char *  fileName);   // 打印值到文件
 23 char *  GetValue( int  val);                            // 计算
 24 char *  SubGetValue( char *  , int );                      
 25
 26
 27 int  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 计算阶乘的值
 53 char *  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
 71 char *  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 // 得到计算阶乘的值,此函数为新增
 96 int  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 // 返回结果的位数
115 int  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 // -------------
130 char   *  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 // -------------
151 void  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
177 void  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

好了,不说了. 
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值