椭圆积分——从不会到会 still 不会
本章又名:积分积着积着发现反函数变成椭圆函数了,很气。
前置知识
三角函数、反三角函数、一点定积分、知道 1−x2 积出来是 arcsin、会求导、最好见过椭圆方程。
约定俗成:下文用 E 表示第二类椭圆积分、F 表示第一类椭圆积分、Π 表示第三类,虽然这仨符号长得完全不像人名但国际数学界都这么叫,忍一下。
引子:椭圆弧长
你画一个椭圆
a2x2+b2y2=1
想用高中那一套求个周长,然后发现弧长公式长这样:
s=∫02πa2sin2θ+b2cos2θdθ
化简一下,令离心率 e=1−a2b2,a>b:
s=4a∫02π1−e2sin2θdθ
这就是第二类完全椭圆积分 E(e)。
所以椭圆积分最早就是算椭圆周长算出来的,名字很诚实。
第一类椭圆积分 F(φ,k)
定义:
F(φ,k)=∫0φ1−k2sin2θdθ
其中 k∈[0,1) 叫模数,φ 叫振幅。
当 φ=2π 时,叫完全椭圆积分,记作 K(k):
K(k)=∫02π1−k2sin2θdθ
特殊值
- k=0:K(0)=2π,退化回普通积分。
- k→1−:K(k)→+∞,因为 1−sin2θ 在 θ=2π 附近变成 0,分母爆炸。
它积出来是啥?
很不幸,第一类椭圆积分没有初等函数形式。就像 ∫e−x2dx 积不出来要叫 erf 一样,椭圆积分也要被赐名为 F、K。
但你可以查表,或者用 AGM 算法(后面讲)。
第二类椭圆积分 E(φ,k)
定义:
E(φ,k)=∫0φ1−k2sin2θdθ
完全形式:
E(k)=∫02π1−k2sin2θdθ
特殊值
- k=0:E(0)=2π。
- k=1:E(1)=1(因为 ∫02πcosθdθ=1)。
椭圆周长公式
椭圆周长 C=4aE(e),其中 e=1−a2b2。所以别再说椭圆周长没公式了,它有,只是不是初等函数。
第三类椭圆积分 Π(n;φ,k)
定义:
Π(n;φ,k)=∫0φ(1−nsin2θ)1−k2sin2θdθ
多了一个参数 n,叫特征值。完全形式记为 Π(n;k)。
这个用得比前两类少,但物理里经常冒出来(比如电磁学、摆的大幅度周期)。
三个参数,非常不讲道理,建议先记住形式。
它们之间的关系
Legendre 关系:
E(k)K(k′)+E(k′)K(k)−K(k)K(k′)=2π
其中 k′=1−k2 叫互补模数。
这个式子看起来对称,实际上可以拿来当恒等式用,也可以拿来检查 AGM 算得对不对。
求导和恒等式
dkdK(k)=k(1−k2)E(k)−(1−k2)K(k)
dkdE(k)=kE(k)−K(k)
证明基本就是积分号下求导然后化简,比较机械,但草稿纸需要大一点。
AGM 算法——手算 K(k)
K(k) 可以用算术-几何平均(AGM)快速算:
设 a0=1,b0=1−k2=k′,然后迭代:
an+1=2an+bn
bn+1=anbn
cn+1=2an−bn
当 n 足够大时,an≈bn≈M(a0,b0),AGM 收敛非常快,每轮有效位数翻倍。
第一类完全椭圆积分:
K(k)=2M(1,k′)π
第二类完全椭圆积分:
E(k)=2M(a0,b0)π(1−n=0∑∞2n−1cn2)
每次看到这个求和都感叹,到底是谁先想到的……
代码实现:
#include <bits/stdc++.h>
using namespace std;
typedef long double ld;
const ld PI = acosl(-1.0);
// 返回 K(k), E(k)
pair<ld, ld> elliptic_K_E(ld k) {
ld a = 1.0, b = sqrtl(1 - k * k), c = k;
ld sum = 0.0;
ld pw2 = 1.0; // 2^n
for (int n = 0; n < 10; ++n) { // 10 次迭代精度足够
ld an = (a + b) / 2.0;
ld bn = sqrtl(a * b);
ld cn = (a - b) / 2.0;
sum += pw2 * cn * cn;
pw2 *= 2.0;
a = an; b = bn; c = cn;
}
ld K = PI / (2 * a);
ld E = K * (1.0 - sum / 2.0); // 注意系数写法
return {K, E};
}
int main() {
ld k = 0.5;
auto [K, E] = elliptic_K_E(k);
cout << "K(" << k << ") = " << K << "\n";
cout << "E(" << k << ") = " << E << "\n";
return 0;
}
坑点:
- k 太接近 1 时 K 会很大,double 可能不够,建议用 long double。
- 初始 b0 是 1−k2,不是 k。
- 上面的 E 公式系数容易记混,建议每次用 E(0)=2π 和 E(1)=1 验证。
椭圆函数 Jacobi sn, cn, dn
椭圆积分是 Jacobi 椭圆函数的反函数。就像 arcsin 和 sin 互为反函数一样。
定义:如果
u=F(φ,k)=∫0φ1−k2sin2θdθ
那么 Jacobi 椭圆函数:
sn(u,k)=sinφ
cn(u,k)=cosφ
dn(u,k)=1−k2sin2φ
基本恒等式
sn2(u,k)+cn2(u,k)=1
k2sn2(u,k)+dn2(u,k)=1
导数
dudsn(u,k)=cn(u,k)dn(u,k)
dudcn(u,k)=−sn(u,k)dn(u,k)
duddn(u,k)=−k2sn(u,k)cn(u,k)
是不是很像三角函数?当 k=0 时 sn→sin,cn→cos,dn→1。
例题
例 1:单摆大角度周期
单摆小角度周期 T0=2πgL。大角度精确解:
T=4gLK(sin2θ0)
其中 θ0 是最大摆角。所以第一类完全椭圆积分就是单摆的修正因子。
例 2:椭圆周长
椭圆 a2x2+b2y2=1,a>b,离心率 e=1−a2b2。
C=4aE(e)
如果 a=5,b=3,则 e=54,C=20E(0.8)。
例 3:数值验证
用 AGM 算 K(0) 和 E(0),应该得到 2π。如果算出来不对,说明你 b0 写错了。
总结
- 椭圆积分有三类:F,E,Π,分别是 ⋯1、⋯、(1−nsin2)⋯1 的积分。
- 完全椭圆积分就是上限到 2π。
- 椭圆函数是椭圆积分的反函数,Jacobi sn/cn/dn 是三角函数的推广。
- AGM 能高效算 K 和 E。
- 椭圆积分无处不在:椭圆周长、单摆、物理、密码学(某些椭圆曲线相关的东西)。
参考与推荐阅读
- OEIS 和各种手册里的椭圆积分表
- Abramowitz & Stegun: Handbook of Mathematical Functions
- 如果你想硬刚推导:Whittaker & Watson《A Course of Modern Analysis》
最后,如果你问椭圆积分有什么用,我只能说:它至少能算出椭圆到底有多长,而圆可以直接用 2πr,所以椭圆比圆更高级,没毛病。