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!的精确位数。
位数的确定解决之后,就看看如何计算了.
看看如下代码:
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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

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日
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?