• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
彭旭
天空不留痕迹,鸟儿却已飞过……
博客园    首页    新随笔    联系   管理    订阅  订阅

大数阶乘

前言

  阶乘的定义

    不了解的朋友可先了解一下,点击这里。
    所以,如果是比较小的数的阶乘的话,用递归之类的还能用。稍大一点儿已有的数据类型就没办法存储了,所以此次用数组存储,如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...+log10n 
    循环求和,就能算得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();
}

 

知识共享许可协议
本文 由 彭旭 创作,采用 知识共享 署名-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
posted @ 2010-05-11 21:00  彭旭  阅读(312)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3