大数阶乘

前言

  阶乘的定义

    不了解的朋友可先了解一下,点击这里
    所以,如果是比较小的数的阶乘的话,用递归之类的还能用。稍大一点儿已有的数据类型就没办法存储了,所以此次用数组存储,如uint[] result,result[0]存个位,result[1]存十位,依次类推。
    其实感觉跟小时候算乘法一样。从个位开始乘于乘数,超10进一位。如下:

             123456789

          ×       8

1111111101

    可以把123456789本身看成数组,这样就简单多了。
    不过听说4.0里有 System.Numeric.BigInteger,没装,具体不知道。

准备

  n! 的位数

    可以将n!表示成10的次幂,即n!=10M,则不小于M的最小整数就是 n!的位数,对该式两边取对数,即:

    M=log10n!

    可得: 
    M = log101+log102+log103...+log10
    循环求和,就能算得M值,M取整就是n!的精确位数。

正文

    代码如下:
public string Factorial(int n)
{
double len = 1.0;
for (int a = 1; a <= n; a++) len += Math.Log10((double)a);
int length = (int)len; //n! 的位数

uint[] result = new uint[length]; //将阶乘的值以数组方式存储
result[0] = 1;
int i = 0; //i,j 均为下列循环中的变量,在此处声明
int j = 0;
int valid = 1; //下面循环中 i! 的位数
long tmp = 0; //控制进位
for (i = 2; i <= n; i++) //循环从 2 开始,因为 0! = 1 、1! = 1
{
tmp
= 0;
for (j = 0; j < valid; j++)
{
long r = result[j] * i + tmp;
result[j]
= (uint)(r % 10);
tmp
= r / 10;
}
while (tmp != 0) //最高位进位
{
result[valid
++] = (uint)(tmp % 10);
tmp
/= 10;
}
}
//以字符串的形式返回
StringBuilder sb = new StringBuilder();
for (int p = length - 1; p >= 0; p--)
{
sb.Append(result[p]);
}
return sb.ToString();
}
原文地址:https://www.cnblogs.com/ainijiutian/p/1732925.html