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

2
//////////////////////////////////////////////////////////////////////////3
// Date created: 2005/07/124
// Author: Confach Zhang5
// 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
//函数GetValue47
// 求得计算结果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
//函数GetBitLength111
// 求得计算结果的位数,本函数为新增加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
//函数:Initialize124
// 初始化存储结果的数组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
//函数:PrintValue145
// 将结果输入到屏幕上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
//函数:PrintValue170
// 将结果输入到一个文件中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

下载代码
本贴转自:http://confach.cnblogs.com/archive/2005/07/14/192703.html
本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利
This posting is provided "AS IS" with no warranties, and confers no rights.



浙公网安备 33010602011771号