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