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

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
宝玉的分享
宝玉的分享
G
Google Developers Blog
T
Tailwind CSS Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
V2EX
V
Visual Studio Blog
博客园 - Franky
S
SegmentFault 最新的问题
Jina AI
Jina AI
爱范儿
爱范儿
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
C
Check Point Blog
月光博客
月光博客
P
Proofpoint News Feed
T
The Blog of Author Tim Ferriss
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
Martin Fowler
Martin Fowler

博客园 - 彭旭

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();
}