“阶乘”(factorial)在信息学竞赛中具有重要角色,更广泛的说,“阶乘”在数学领域也是占有重要地位。在许多人刚刚学习计算机语言的时候,大多会被要求写一个算阶乘的程序,而在学习高精度算法的时候,也会写一个计算较大数字阶乘的程序。不过,在实际的运用之中,可能遇到更大数字的阶乘计算和不同要求的阶乘结果,例如:TOJ(同济大学ACM网络题库,http://acm.tongji.edu.cn/problem.php)的1016题——“求N!左边第二位的数字”,这就需要一定的精度思考了。
可是我们通常对于较大数字阶乘的要求是求结果位数或前几位数字,这怎么办呢?
在刘汝佳的《算法艺术与信息学竞赛》一书中,(Page241)介绍了Stirling公式:
其中的~符号是指“同阶”或“相当”,即两者随n增加的大致速度相同,在n较大时,两者极其相近。
这是一个极限的概念(现行教材高二下学期数学内容),属于微分学内容,准确写法为:
但遗憾的是在《算法艺术与信息学竞赛》书中只提供了这个算式,并无他物!
本人近日看到一本数学科普读物——《好玩的数学——不可思议的e》(陈任政著,科学出版社),其中5.12节简介了Stirling逼近近似算阶乘,本人感到好奇,于是对这种算法的具体步骤进行了分析,并研究了它的精确度,故为本文。在
在1730年,棣莫弗(棣,音Dì)(法国数学家,Abraham De Moiver,1667~1754)发表的《分析杂论》中首先对n!地一个无穷级数展开式给出了近似公式:
但是,现在我们叫这个式子为“Stirling逼近”,中文叫做“斯特林逼近”,这是为什么呢?
因为棣莫弗的朋友苏格兰数学家斯特林(James Stirling,1696~1770)在同年的《微分法或无穷级数的简述》中也给出了等价的级数。
事实上,棣莫弗首先得到的式子是
但是,他没有把C求出来。而斯特林则利用棣莫弗的发现做了探讨,求出了
这些式子的来源是一个无穷级数展开式:
这里介绍一下,还没上高中的同学还没有学到,“乘方”的逆运算有两种:开方和对数。
对于一个幂:
当底数为10的时候,叫做常用底数,简写做
至于e的含义:e是重要性仅次于π的数,是极限论的主要内容,具体的说,即:
意思是当n趋向于正的无限大的时候,
e是无理数,即无限不循环小数,也是超越数,即不能满足某个整数系数代数方程的数(不能满足某个整数系数代数方程的数叫做代数数)。
目前e只算到了几千位。
e=2.718281828459045235360287471352662497757247093...
特别说明的是,在Pascal语言中,exp(n)函数就是e的n次方。
另外,有个著名的公式被成为“整个数学中最卓越的公式”:
其中的i为虚数的单位,
这是欧拉(瑞士数学家,Leonhard Euler,1707~1783)发现的!所以称作“欧拉公式”。
不过,真正的欧拉公式是:
那个“最卓越的公式”只是欧拉公式的一个推倒公式。
言归正传,由公式
两边同时取e的幂,得
再经过近似等处理(这些处理比较麻烦,而且牵扯到微积分内容),我们得到了Stirling公式:
注:在本文后部有Stirling公式的推倒过程。
当然,我们可以得到它得更具体形式:
其中的θ是不定的,在(0,1)区间之内。
讲到这里,我们有了公式,可以开始计算了。
但是,我们计算什么呢?难道我们要计算N!的值吗?
虽然这个式子比阶乘原始计算式简单,但是实际计算的时候仍然得到的将是上百上千位的数字,而且这个式子毕竟是近似公式,无法真正得到确切得数!
难道我们辛苦的到的式子无用了吗?
答案当然是否定的!我们可以求N!的位数!
求位数的方法是取常用对数(以10为底的对数)。那,这是为什么呢?看看下表:
n |
|
n位数 |
|
1 |
0.000000 |
1 |
|
10 |
1.000000 |
2 |
|
100 |
2.000000 |
3 |
|
1000 |
3.000000 |
4 |
|
10000 |
4.000000 |
5 |
|
100000 |
5.000000 |
6 |
|
1000000 |
6.000000 |
7 |
|
10000000 |
|