数学 / 排列组合 · 从计数原理到 P(n,k) 与 C(n,k) / 阶乘与中心系数的渐近 待审核 22 / 25
Stirling 公式 · 4ⁿ/√(πn)

阶乘与中心系数的渐近

线性近似处理的是 x0x \to 0:把 (1+x)n(1+x)^n 的高次项丢掉,误差随 xx 的幂衰减。本页处理另一端 nn \to \infty:阶乘与组合数本身没有初等闭式可以化简,但它们的量级有。Stirling 公式(Stirling's approximation)把 n!n! 写成一个初等表达式,误差随 nn 增大而收缩;代进 C(2n,n)C(2n, n) 就得到中心二项式系数的量级,而这正是判断一个指数级算法有多大的常用工具。

1 · Stirling 公式的相对误差

Stirling · n! ≈ √(2πn)·(n/e)ⁿ
n!2πn(ne)nn! \sim \sqrt{2\pi n}\, \left(\frac{n}{e}\right)^n

记号 \sim 指两边之比趋于 11,不是两边之差趋于 00——n=100n = 100 时两者的差已有 1015410^{154} 量级,比值却只差万分之一。更精确的展开给出 n!=2πn(n/e)n(1+112n+1288n2+)n! = \sqrt{2\pi n}\,(n/e)^n \left(1 + \frac{1}{12n} + \frac{1}{288n^2} + \cdots\right),括号里的修正项恒为正,近似值因此恒小于精确值,相对误差的主项是 1/(12n)1/(12n)

nn 实测(logFactoriallogStirling 在对数域相减,再取 1eΔ1 - e^{\Delta}):

nn 相对误差 1/(12n)1/(12n) 误差 ×12n\times\, 12n
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

最右一列从下方单调逼近 11nn 扫到 500500 仍未越过(n=500n = 500 处为 0.999920.99992)。值得记住的是第一行:n=1n = 1 时公式给出 0.92210.9221 而非 11,只差 7.8%7.8\%——一个只在 nn \to \infty 时才被声明成立的近似,在最小的那个 nn 上已经准到两位有效数字。

图 1-1 · Stirling 近似的相对误差与 1/(12n)1/(12n) 参考线。可拖动 nn 对照精确值、近似值与误差的 12n12n 倍,切到第二档则改为对照 C(2n,n)/4nC(2n, n)/4^n 与它的渐近值 1/√(πn)。

2 · 中心二项式系数的量级

把 Stirling 公式代进 C(2n,n)=(2n)!/(n!)2C(2n, n) = (2n)!/(n!)^2,三步即得:

C(2n,n)4πn(2n/e)2n(2πn(n/e)n)2=4πn  4nn2ne2n2πnn2ne2n=4nπnC(2n,\, n) \sim \frac{\sqrt{4\pi n}\, (2n/e)^{2n}}{\left(\sqrt{2\pi n}\, (n/e)^n\right)^2} = \frac{\sqrt{4\pi n}\; 4^n\, n^{2n} e^{-2n}}{2\pi n \cdot n^{2n} e^{-2n}} = \frac{4^n}{\sqrt{\pi n}}

分子分母的 n2ne2nn^{2n} e^{-2n} 整段抵消,只剩 4n4^n 与两个根号之商 4πn/(2πn)=1/πn\sqrt{4\pi n}/(2\pi n) = 1/\sqrt{\pi n}

这个式子给出 Pascal 三角与二项式定理的一条量级结论:第 2n2n 行全部元素之和是 4n4^n,而其中最大的一项只占 1/πn1/\sqrt{\pi n}。行越往下越平,没有哪一项能占住常数比例——n=100n = 100 时最大项占全行的 5.63%5.63\%n=5000n = 5000 时只剩 0.798%0.798\%。图 1-1 的第二档给出这两条曲线的贴合程度:比值在 n=50n = 50 时为 0.997500.99750n=5000n = 5000 时为 0.9999750.999975,缺口的主项是 1/(8n)1/(8n),实测偏差在 1/(64n2)1/(64n^2) 之内。

3 · 复杂度里的量级排序

2n2^nC(n,n/2)C(n, n/2)n!n! 三者的排序靠的就是这类估计。nn 为偶数时 C(n,n/2)2n2/(πn)C(n, n/2) \sim 2^n \sqrt{2/(\pi n)}:枚举「恰好一半」的子集比枚举全部子集只小一个 n\sqrt{n} 因子,二者是同一量级的指数,把算法从前者改成后者不会换来实质加速。n!n! 则完全不同,取对数得 lnn!nlnnn\ln n! \sim n \ln n - n,比 2n2^nnln2n \ln 2 高出一个 lnn\ln n 因子。

Catalan 数可以顺着同一条路算:Cn=C(2n,n)/(n+1)C_n = C(2n, n)/(n+1),除掉的 n+1n+1 直接落到渐近式上,

Cn4nn3/2πC_n \sim \frac{4^n}{n^{3/2}\sqrt{\pi}}

比中心系数多掉一个 nn 的因子。这条式子收敛得比 C(2n,n)C(2n, n) 慢:实测 n=100n = 100 时比值才 0.98890.9889n=1000n = 10000.99890.9989,因为 n+1n+1nn 之差本身就是 O(1/n)O(1/n) 的相对偏差。

4 · 对数域的计算路线

警示 · 对数只推迟溢出,不取消溢出。fact(171)Infinity;改走 logFactorial 累加 lni\ln iMath.exp(logFactorial(n)) 同样在 n=171n = 171 变成 Infinityn=170n = 170 时仍给出 7.2574×103067.2574 \times 10^{306})。真正不溢出的是 lnn!\ln n! 本身:logFactorial(100000) 稳稳地等于 1051299.221051299.22。所以能用对数救回来的只有比值、比例与量级,最终结果一旦真是天文数字,就没有 Number 可以装。

一个更隐蔽的坑出在 C(2n,n)/4nC(2n, n)/4^n 上。这个比值恒小于 11,按定义直算却先于分母崩掉:comb(2n, n)n=511n = 511 已是 Infinity,而 4n4^n 撑到 n=512n = 512 才溢出,n=511n = 511 处算出的是 Infinity 而非真值 0.02500.0250。本页的 centralRatio 因此写成 exp(ln(2n)!2lnn!2nln2)\exp(\ln (2n)! - 2 \ln n! - 2n \ln 2)n=5000n = 5000 照样有值。

两条路线各有适用面:要精确整数就走大整数与素因子分解(见组合数的计算),要量级与比例就走本页的渐近式与对数。对数路线的另一处代价在精度。Math.exp(logFactorial(170)) 给出 7.257415615309707e+306,朴素累乘 fact(170) 给出 7.257415615307994e+306,两者从第 12 位有效数字起分家,那是 170170Math.log 与一次 Math.exp 攒下的舍入。

5 · 参考文献

  1. Stirling's approximation. Wikipedia. Stirling 公式的多种推导、误差界与 1/(12n)1/(12n) 修正项。https://en.wikipedia.org/wiki/Stirling%27s_approximation
  2. Central binomial coefficient. Wikipedia. C(2n,n)C(2n, n) 的性质、渐近式与相关恒等式。https://en.wikipedia.org/wiki/Central_binomial_coefficient
  3. Catalan number. Wikipedia. Catalan 数的定义、组合解释与 4nn3/2π1/24^n n^{-3/2}\pi^{-1/2} 渐近。https://en.wikipedia.org/wiki/Catalan_number