阶乘与中心系数的渐近
线性近似处理的是 :把 的高次项丢掉,误差随 的幂衰减。本页处理另一端 :阶乘与组合数本身没有初等闭式可以化简,但它们的量级有。Stirling 公式(Stirling's approximation)把 写成一个初等表达式,误差随 增大而收缩;代进 就得到中心二项式系数的量级,而这正是判断一个指数级算法有多大的常用工具。
1 · Stirling 公式的相对误差
记号 指两边之比趋于 ,不是两边之差趋于 —— 时两者的差已有 量级,比值却只差万分之一。更精确的展开给出 ,括号里的修正项恒为正,近似值因此恒小于精确值,相对误差的主项是 。
逐
实测(logFactorial 与 logStirling 在对数域相减,再取
):
| 相对误差 | 误差 | ||
|---|---|---|---|
| 1 | 7.7863% | 8.3333% | 0.93436 |
| 2 | 4.0498% | 4.1667% | 0.97195 |
| 5 | 1.6507% | 1.6667% | 0.99042 |
| 10 | 0.82960% | 0.83333% | 0.99552 |
| 20 | 0.41577% | 0.41667% | 0.99784 |
| 50 | 0.16653% | 0.16667% | 0.99915 |
| 100 | 0.083298% | 0.083333% | 0.99958 |
最右一列从下方单调逼近 , 扫到 仍未越过( 处为 )。值得记住的是第一行: 时公式给出 而非 ,只差 ——一个只在 时才被声明成立的近似,在最小的那个 上已经准到两位有效数字。
2 · 中心二项式系数的量级
把 Stirling 公式代进 ,三步即得:
分子分母的 整段抵消,只剩 与两个根号之商 。
这个式子给出 Pascal 三角与二项式定理的一条量级结论:第 行全部元素之和是 ,而其中最大的一项只占 。行越往下越平,没有哪一项能占住常数比例—— 时最大项占全行的 , 时只剩 。图 1-1 的第二档给出这两条曲线的贴合程度:比值在 时为 , 时为 ,缺口的主项是 ,实测偏差在 之内。
3 · 复杂度里的量级排序
、 与 三者的排序靠的就是这类估计。 为偶数时 :枚举「恰好一半」的子集比枚举全部子集只小一个 因子,二者是同一量级的指数,把算法从前者改成后者不会换来实质加速。 则完全不同,取对数得 ,比 的 高出一个 因子。
Catalan 数可以顺着同一条路算:,除掉的 直接落到渐近式上,
比中心系数多掉一个 的因子。这条式子收敛得比 慢:实测 时比值才 , 时 ,因为 与 之差本身就是 的相对偏差。
4 · 对数域的计算路线
警示 · 对数只推迟溢出,不取消溢出。fact(171) 是 Infinity;改走 logFactorial 累加
,Math.exp(logFactorial(n)) 同样在
变成 Infinity(
时仍给出
)。真正不溢出的是
本身:logFactorial(100000) 稳稳地等于
。所以能用对数救回来的只有比值、比例与量级,最终结果一旦真是天文数字,就没有 Number 可以装。
一个更隐蔽的坑出在
上。这个比值恒小于
,按定义直算却先于分母崩掉:comb(2n, n) 在
已是 Infinity,而
撑到
才溢出,
处算出的是 Infinity 而非真值
。本页的 centralRatio 因此写成
,
照样有值。
两条路线各有适用面:要精确整数就走大整数与素因子分解(见组合数的计算),要量级与比例就走本页的渐近式与对数。对数路线的另一处代价在精度。Math.exp(logFactorial(170)) 给出 7.257415615309707e+306,朴素累乘 fact(170) 给出
7.257415615307994e+306,两者从第 12 位有效数字起分家,那是
次 Math.log 与一次 Math.exp 攒下的舍入。
5 · 参考文献
- Stirling's approximation. Wikipedia. Stirling 公式的多种推导、误差界与 修正项。https://en.wikipedia.org/wiki/Stirling%27s_approximation
- Central binomial coefficient. Wikipedia. 的性质、渐近式与相关恒等式。https://en.wikipedia.org/wiki/Central_binomial_coefficient
- Catalan number. Wikipedia. Catalan 数的定义、组合解释与 渐近。https://en.wikipedia.org/wiki/Catalan_number