出自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!的精确位数。
位数的确定解决之后,就看看如何计算了.
看看如下代码:
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
//
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
好了,不说了.
本文介绍了一种使用数组存储和计算大数阶乘的方法,解决了传统数据类型无法直接存储大数的问题,并通过精确计算阶乘的位数确保结果正确。
2613

被折叠的 条评论
为什么被折叠?



