您的位置:知识库 » 其他分类

计算任意数值的阶乘

作者: eaglet  来源: 博客园  发布时间: 2009-08-20 09:56  阅读: 1272 次  推荐: 0   原文链接   [收藏]  

     谈到计算阶乘,大家可能会觉得比较简单,不就是一个循环从1一直乘到n吗?是的,确实是这样,但由于计算机的计算精度问题,利用计算机提供的现成的整数类型,我们最多可以计算到22! = 17196083355034583040 再大了,64位整形就无法存储。那么如果我们想计算100! 怎么办呢?eaglet 以前在博问中回答过类似问题,今天有空把它整理出来,供大家参考。

     要实现任意数值的阶乘,最简单的办法就是自己实现一个整数类型,这个整数类型可以像int, long 这些类型一样实现加和乘的操作,但没有大小限制。下面就给出eaglet 做的十进制无符号整形类。这个类只实现了加法和乘法操作,没有实现减法和除法,但用作阶乘已经足够了,减法和除法大家有兴趣可以自己补充。

加法是基础

算法很简单,就是从个位开始按位相加,如果有进位,就进位。

乘法的方法是将乘数从各位开始逐位和被乘数相乘,然后再将相乘后得到的数累加,这个方法和手工计算乘法的方法是一样的。

个人感觉这两种方法的效率应该不是最高的,如果哪位TX有更高效的算法,也不妨一起讨论一下。

下面给出代码

   
 /// 
/// 十机制无符号整数类
///
public class DecimalNumber
{
List
<byte> _Data;

public List<byte> Data
{
get
{
return _Data;
}
}

public int Length
{
get
{
return _Data.Count;
}
}

public DecimalNumber()
{
_Data
= new List<byte>();
}

public DecimalNumber(byte[] data)
{
foreach (byte b in data)
{
System.Diagnostics.Debug.Assert(b
>= 0 && b <= 9);
}

_Data
= new List<byte>(data);
}

public DecimalNumber(List<byte> data)
{
foreach (byte b in data)
{
System.Diagnostics.Debug.Assert(b
>= 0 && b <= 9);
}

_Data
= data;
}

///
/// 1位10机制数和10进制序列相乘
///
///
/// 10进制序列
/// 1位10机制数
/// 10的幂数
///
private static List<byte> Multiply(List<byte> s, byte d, int power)
{
System.Diagnostics.Debug.Assert(power
>= 0);
System.Diagnostics.Debug.Assert(d
>= 0 && d <= 9);

List
<byte> result = new List<byte>();

for (int i = 0; i < power; i++)
{
result.Add(
0);
}

byte carry = 0; //进位

foreach (byte si in s)
{
System.Diagnostics.Debug.Assert(si
>= 0 && si <= 9);

byte r = (byte)(si * d + carry);
byte m = (byte)(r % 10);
carry
= (byte)(r / 10);
result.Add(m);
}

if (carry > 0)
{
result.Add(carry);
}


return result;
}

///
/// 两个10进制序列相加
///
/// 序列1
/// 序列2
/// 相加后的序列
private static List<byte> Plus(List<byte> s1, List<byte> s2)
{
List
<byte> result = new List<byte>();

int c1 = s1.Count;
int c2 = s2.Count;

if (c1 > c2)
{
for (int i = 0; i < c1 - c2; i++)
{
s2.Add(
0);
}
}
else if (c1 < c2)
{
for (int i = 0; i < c2 - c1; i++)
{
s1.Add(
0);
}
}

byte carry = 0; //进位

for (int i = 0; i < s1.Count; i++)
{
System.Diagnostics.Debug.Assert(s1[i]
>= 0 && s1[i] <= 9);
System.Diagnostics.Debug.Assert(s2[i]
>= 0 && s2[i] <= 9);

byte r = (byte)(s1[i] + s2[i] + carry);
byte m = (byte)(r % 10);
carry
= (byte)(r / 10);
result.Add(m);
}

if (carry > 0)
{
result.Add(carry);
}

return result;
}

public static implicit operator DecimalNumber(string value)
{
List
<byte> data = new List<byte>();

for (int i = value.Length - 1; i >= 0; i--)
{
data.Add(
byte.Parse(value[i].ToString()));
}

return new DecimalNumber(data);
}

public static implicit operator DecimalNumber(int value)
{
System.Diagnostics.Debug.Assert(value
>= 0);
return value.ToString();
}

public static DecimalNumber operator ++(DecimalNumber d)
{
return d + new DecimalNumber(new byte[] { 1 });
}

public static DecimalNumber operator +(DecimalNumber d1, int d2)
{
System.Diagnostics.Debug.Assert(d2
>= 0);

return d1 + d2.ToString();
}

public static DecimalNumber operator +(DecimalNumber d1, DecimalNumber d2)
{
return new DecimalNumber(Plus(d1.Data, d2.Data));
}

public static DecimalNumber operator *(DecimalNumber d1, DecimalNumber d2)
{
List
<byte>> multiplicationSerial = new List<byte>>();

for (int i = 0; i < d1.Data.Count; i++)
{
multiplicationSerial.Add(Multiply(d2.Data, d1.Data[i], i));
}

List
<byte> result = new List<byte>();

foreach (List<byte> s in multiplicationSerial)
{
result
= Plus(s, result);
}

return new DecimalNumber(result);
}

public override string ToString()
{
StringBuilder str
= new StringBuilder();

for (int i = _Data.Count - 1; i >= 0; i--)
{
str.Append(_Data[i].ToString());
}

return str.ToString();
}
}

有了这个类,我们计算阶乘就简单了

下面是计算任意数阶乘的函数

        static public DecimalNumber Factorial(int n)
{
if (n < 0)
{
throw new System.ArgumentException("n < 0!");
}

DecimalNumber result
= 1;

for (int i = 1; i <= n; i++)
{
result
*= i;
}

return result;
}


用这个函数,我们计算0 到 50 的阶乘

 

 for (int i = 0; i <= 50; i++)
{
Console.WriteLine(
string.Format("{0}! = {1}", i, Factorial(i)));
}

 

 

看看结果:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 1307674368000
16! = 20922789888000
17! = 355687428096000
18! = 6402373705728000
19! = 121645100408832000
20! = 2432902008176640000
21! = 51090942171709440000
22! = 1124000727777607680000
23! = 25852016738884976640000
24! = 620448401733239439360000
25! = 15511210043330985984000000
26! = 403291461126605635584000000
27! = 10888869450418352160768000000
28! = 304888344611713860501504000000
29! = 8841761993739701954543616000000
30! = 265252859812191058636308480000000
31! = 8222838654177922817725562880000000
32! = 263130836933693530167218012160000000
33! = 8683317618811886495518194401280000000
34! = 295232799039604140847618609643520000000
35! = 10333147966386144929666651337523200000000
36! = 371993326789901217467999448150835200000000
37! = 13763753091226345046315979581580902400000000
38! = 523022617466601111760007224100074291200000000
39! = 20397882081197443358640281739902897356800000000
40! = 815915283247897734345611269596115894272000000000
41! = 33452526613163807108170062053440751665152000000000
42! = 1405006117752879898543142606244511569936384000000000
43! = 60415263063373835637355132068513997507264512000000000
44! = 2658271574788448768043625811014615890319638528000000000
45! = 119622220865480194561963161495657715064383733760000000000
46! = 5502622159812088949850305428800254892961651752960000000000
47! = 258623241511168180642964355153611979969197632389120000000000
48! = 12413915592536072670862289047373375038521486354677760000000000
49! = 608281864034267560872252163321295376887552831379210240000000000
50! = 30414093201713378043612608166064768844377641568960512000000000000

0
0
标签:算法

其他分类热门文章

    其他分类最新文章

      最新新闻

        热门新闻