惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
J
Java Code Geeks
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
G
Google Developers Blog
Engineering at Meta
Engineering at Meta
量子位
S
SegmentFault 最新的问题
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
A
About on SuperTechFans
P
Proofpoint News Feed
Last Week in AI
Last Week in AI
Recent Announcements
Recent Announcements
腾讯CDC
I
InfoQ
F
Fortinet All Blogs
Hugging Face - Blog
Hugging Face - Blog
Blog — PlanetScale
Blog — PlanetScale
H
Help Net Security
爱范儿
爱范儿

博客园 - 彭旭

VNC远程Gnome图形桌面(openEuler 20.03 LTS系统) [WPF]控件应用多个样式 [ASP.NET MVC] Real-time之HTML5 服务器发送事件(server-sent event) [WCF]DomainServices客户端操作异常处理 [Silverlight]监听指定控件(FrameworkElement)的依赖属性(DependencyProperty)的更改 [Silverlight]键盘钩子KeyboardHook [Chrome扩展]屏蔽Google搜索结果重定向 Linq Distinct扩展 [Winform/C#]点击工作区域移动窗体 [WinForm] C#避免Panel(ScrollableControl)的子控件获取焦点时滚动条自动滚动 C#远程连接Oracle数据库(不安装客户端) RichTextBox.MouseWheel事件控制父控件Panel的内容滚动 ID3v1信息结构(MP3文件)的读取、修改(C#) 在线编辑Office文件 SQL优化 将自然数分解为若干连续的自然数 小写金额转换为大写金额 查看文件夹大小及占用空间 VS2005开发WAP网站初识 - 彭旭 - 博客园
大数阶乘
彭旭 · 2010-05-11 · via 博客园 - 彭旭

前言

  阶乘的定义

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