
一句话用一条高次多项式精确穿过一排等间距的点点越多曲线在两端甩得越厉害。这篇换个角度看它。不比误差多大——误差多少算大总可以争论——只看值域曲线有没有跑到函数根本不可能到达的地方去。一、先锁定答案的范围Runge 1901 年用的函数f(x)1125x2,x∈[−1, 1]f(x) \frac{1}{125x^2}, \qquad x \in [-1,\ 1]f(x)125x21,x∈[−1,1]在动手拟合之前先把它的值域算出来。这一步很重要它给了我们一把尺子。位置值x0x 0x0峰顶111x±0.5x \pm 0.5x±0.5≈0.138\approx 0.138≈0.138x±1x \pm 1x±1最低1/26≈0.0381/26 \approx 0.0381/26≈0.038值域 [0.038, 1][0.038,\ 1][0.038,1]宽度不到 1。而且这里有两条代数上锁死的约束不可能超过 1。分母125x2≥1125x^2 \ge 1125x2≥1所以整个分式≤1\le 1≤1。不可能是负数。分母恒正分子是 1。这两条不是观察到的现象是推出来的。所以任何落在[0.038, 1][0.038,\ 1][0.038,1]之外的值都是错的答案不是不够准的答案。这就是这篇文章的尺子。二、真实函数长什么样下面所有图的 y 轴都固定在[−0.5, 1.5][-0.5,\ 1.5][−0.5,1.5]中间用▒标出合法值域[0.038,1][0.038, 1][0.038,1]。先看基准y 1.5 ┤ 1.2 ┤ 1.0 ┤▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ← 上界不可超过 0.8 ┤▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*▒*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 0.6 ┤▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*▒▒▒*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 0.4 ┤▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*▒▒▒▒▒*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 0.2 ┤▒▒▒▒▒▒▒▒▒▒▒▒**▒▒▒▒▒▒▒▒▒**▒▒▒▒▒▒▒▒▒▒▒▒▒ 0.0 ┤*************▒▒▒▒▒▒▒▒▒▒▒▒************* ← 下界 0.038不可为负 -0.2 ┤ -0.5 ┤ └┬─────────┬─────────┬─────────┬────────┬ -1.0 -0.5 0.0 0.5 1.0 ▒ 合法值域 [0.038, 1] * 真实函数整条曲线老老实实待在灰带里。这是正确的形状。三、11 个等间距点10 次多项式取x−1.0,−0.8,…,1.0x -1.0, -0.8, \dots, 1.0x−1.0,−0.8,…,1.0共 11 个点拟合一个 10 次多项式。它在数学上唯一确定精确穿过全部 11 个点。同一个画框同一条灰带y 1.5 ┤ ↑ ↑ ← 冲出画框 1.2 ┤ o o 1.0 ┤▒▒│▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│▒▒ 0.8 ┤▒▒│▒▒▒▒▒▒▒▒▒▒▒▒▒▒*▒*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│▒▒ 0.6 ┤▒▒│▒▒▒▒▒▒▒▒▒▒▒▒▒*▒▒▒*▒▒▒▒▒▒▒▒▒▒▒▒▒▒│▒▒ 0.4 ┤▒▒o▒▒▒▒▒▒▒▒▒▒▒▒*▒▒▒▒▒*▒▒▒▒▒▒▒▒▒▒▒▒▒o▒▒ 0.2 ┤▒▒▒●▒▒▒▒▒▒▒▒**▒▒▒▒▒▒▒▒▒**▒▒▒▒▒▒▒▒▒●▒▒▒ 0.0 ┤●●●●●●●●●●●●▒▒▒▒▒▒▒▒▒▒▒▒▒●●●●●●●●●●●● -0.2 ┤ o o ← 跑到负数 -0.5 ┤ └┬─────────┬─────────┬─────────┬────────┬ -1.0 -0.5 0.0 0.5 1.0 ▒ 合法值域 * 真实函数 o 插值曲线越界部分 ● 两者重合中间那一大段和基准图几乎分不出差别。但最外侧的两个区间曲线同时冲破了上界和下界。实际数值这条 10 次曲线的值域大约是[−0.4, 1.9][-0.4,\ 1.9][−0.4,1.9]。合法范围宽 0.96它跑出了宽 2.3 的范围。四、21 个点值域膨胀到一百倍点数加密一倍21 个等间距点20 次多项式。现在画框装不下了。要把它完整画出来y 轴得扩到[−60,60][-60, 60][−60,60]——而那样做灰带会被压成贴在零线上的一道细线y 60 ┤ o o │ │ │ 40 ┤ │ │ │ │ o o │ 20 ┤ │ │ │ │ │ │ │ │ │ 0 ┼─●━━━━━●━━━━━━━━━━━━━━━━━━━━━━━━━━●━━━━━● ← 合法值域整条被压成这条线 │ o o -20 ┤ │ │ │ │ │ -40 ┤ -60 ┤ └┬─────────┬─────────┬─────────┬────────┬ -1.0 -0.5 0.0 0.5 1.0值域来到了[−40, 60][-40,\ 60][−40,60]量级。一个最大值锁死在 1 的函数拟合曲线跑到了 60。换成百分比说一个上限 100% 的量被算成了 6000%。五、值域对照表点数次数插值曲线值域约合法值域值域宽度之比54[−0.06, 1.00][-0.06,\ 1.00][−0.06,1.00][0.038,1][0.038, 1][0.038,1]1.1 倍1110[−0.4, 1.9][-0.4,\ 1.9][−0.4,1.9][0.038,1][0.038, 1][0.038,1]2.4 倍2120[−40, 60][-40,\ 60][−40,60][0.038,1][0.038, 1][0.038,1]104 倍4140±105\pm 10^5±105量级[0.038,1][0.038, 1][0.038,1]二十万倍量级示意用文末代码可核对精确值点越多值域膨胀越快。不是收敛慢是真的发散——点数趋于无穷时两端误差无上界地增长。同时注意那个分裂中间段一直在变准两端一直在变烂。不是整体退化是明确的两极分化。六、为什么越界比误差大更有说服力它是定性的错不是定量的差误差 1.9听起来还能接受毕竟数量级不大。但算出了负数不行——原函数严格为正负数在这里不是精度问题是答案不可用。把场景换一下就很清楚这是一条血量插值曲线 → 血量算出负数这是透光率 → 透光率算出负数这是概率密度 → 概率算出负数也算出 190%这类输出没法凑合用它会直接击穿下游逻辑里的所有假设。它直接否掉了一个常见的自检方法这条最反直觉也最该记住。那条 10 次曲线在每一个采样点上都精确等于真实函数误差严格为零● ● ● ● ● ↑ ↑ ↑ ↑ ↑ 误差 0 误差 0 误差 0 误差 0 误差 0 └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ 误差 1.9 误差 0.1 误差 1.9 两端 中间 两端像一根被钉死在 11 个钉子上的橡皮筋。钉子处分毫不差钉子之间疯狂乱甩。所以所有采样点都对上了完全不能说明拟合是好的。如果你的验证只检查采样点龙格现象会百分之百通过检查。真正该检查的是采样点之间而值域越界是最廉价的检测手段——只要比一下 min/max 就行。七、画图时别换 y 轴尺度顺带说一个坑因为上面第三节和第四节正好演示了它。y 轴尺度一变视觉印象就反了y 轴设成 [0, 1] 插值曲线在两端直接离开画框看不见它去哪了 → 错误印象好像只是边上有点小问题 y 轴设成 [-60, 60] 真实函数被压成贴在零线上的一条平线 → 错误印象真实函数是平的两种都在误导。正确做法是把 y 轴固定在真实值域稍微放宽的范围然后把合法值域画成色带让越界部分明确地冲出画框。超出画框这个视觉事实恰好对应超出值域这个数学事实。ax.set_ylim(-0.5,1.5)ax.axhspan(0.038,1.0,colorgreen,alpha0.12,label合法值域)ax.axhline(0,colorgray,lw0.8)那条绿带就是尺子。曲线有多少跑在带子外面一眼可见而且不同点数的图之间可以直接对比。八、正确的做法换点的位置值域就守住了真正的原因不是次数太高。反例很干脆把采样点改成两端密、中间疏同样做高次多项式值域就不越界了。这种摆法叫切比雪夫节点xkcos (kπn)x_k \cos\!\left(\frac{k\pi}{n}\right)xkcos(nkπ)两种点分布等间距11 个点—— 均匀铺开两端稀疏 ●────●────●────●────●────●────●────●────●────● -1.0 0.0 1.0 切比雪夫11 个点—— 两端挤在一起 ●─●───●─────●───────●───────●─────●───●─● -1.0 0.0 1.0 ↑↑ ↑↑ 两端加密 两端加密值域对比次数完全相同等间距10 次切比雪夫10 次曲线值域[−0.4, 1.9][-0.4,\ 1.9][−0.4,1.9]约[0.03, 1.01][0.03,\ 1.01][0.03,1.01]是否越界上下都严重越界几乎不越界最大误差约 1.9约 0.1等间距10 次 切比雪夫10 次 1.5 ┤ ↑ ↑ 1.5 ┤ 1.0 ┤▒▒│▒▒▒▒▒*▒▒▒▒▒▒▒│▒ 1.0 ┤▒▒▒▒▒▒▒▒◉▒▒▒▒▒▒▒▒▒ 0.5 ┤▒▒o▒▒▒*▒▒*▒▒▒▒▒▒o▒ 0.5 ┤▒▒▒▒▒◉▒▒▒▒◉▒▒▒▒▒▒▒ 0.0 ┤●●●●●▒▒▒▒▒▒▒●●●●● 0.0 ┤◉◉◉◉▒▒▒▒▒▒▒▒◉◉◉◉◉▒ -0.5 ┤ o o -0.5 ┤ └────────────────── └────────────────── 上下都冲出灰带 ◉ 两条曲线完全重合 整条待在灰带里切比雪夫节点下这个函数做到1000 次都能收敛到机器精度值域始终贴在[0.03,1.01][0.03, 1.01][0.03,1.01]附近。所以问题不在次数在点摆在哪。九、等间距为什么错直观的说法内部的每个点左右都有邻居夹着位置被约束得很稳。两端的点只有单侧邻居约束天生不足。多项式是全局刚性的——你在中间动一个点整条曲线都跟着变形。而两端最缺约束所以晃得最厉害。它在那里的行为更接近外推而不是插值外推本来就不稳。所以等间距分布的真正毛病是两端采样不足了。多项式这个函数族在区间两端需要更密的信息才能被钉住你却给了它和中间一样的密度。这个错配的放大倍数大约是2n2^n2nnnn是次数——指数级。这正好解释了值域表里那条膨胀曲线11 点时 2 倍21 点时 100 倍41 点时二十万倍。切比雪夫节点正好把密度往两端堆补上了这个缺口。十、核对数字上面都是示意图。这段代码直接把值域打出来importnumpyasnpdefrunge(x):return1.0/(1.025.0*x**2)xsnp.linspace(-1,1,20000)truthrunge(xs)print(f真实函数值域: [{truth.min():.4f},{truth.max():.4f}]\n)fornin[5,11,21,41]:forname,nodesin[(等间距 ,np.linspace(-1,1,n)),(切比雪夫,np.cos(np.arange(n)*np.pi/(n-1))),]:pnp.polyval(np.polyfit(nodes,runge(nodes),n-1),xs)print(f{n:3}点{name}值域 [{p.min():14.3f},{p.max():12.3f}]f 最大误差{np.abs(p-truth).max():12.3f})出图版本带合法值域色带importmatplotlib.pyplotasplt fig,axesplt.subplots(2,2,figsize(12,8))forax,ninzip(axes.flat,[5,11,15,21]):nodesnp.linspace(-1,1,n)pnp.polyval(np.polyfit(nodes,runge(nodes),n-1),xs)ax.axhspan(0.038,1.0,colorgreen,alpha0.12)# 合法值域ax.plot(xs,truth,k-,lw2.5)ax.plot(xs,p,r--,lw1.5)ax.plot(nodes,runge(nodes),ko,ms5)ax.axhline(0,colorgray,lw0.8)ax.set_ylim(-0.5,1.5)# 四张图统一尺度这样才能对比ax.set_title(f{n}个等间距点 | 值域 [{p.min():.2f},{p.max():.2f}])plt.tight_layout();plt.show()四张图共用同一个 y 轴范围所以越界部分会一张比一张冲得更远——这就是龙格现象最该被看到的样子。十一、这就是样条存在的理由高次多项式插值只有一个旋钮次数。想更精确只能升次而升次把值域膨胀一起带上来。这是个绑死的交易。样条换了个旋钮段数。高次多项式想更准就升次 三次样条想更准就切更多段 一条 20 次曲线 7 段三次曲线 o o ╭──╮ ╭──╮ ╭──╮ ╭── │ 值域跑到 ±60 │ │ │ │ │ │ │ │ ●━━━━━━━━━━━━━━━━━━━━━━━━━● ╰──╯──╰──╯──╰──╯──╰── o o ↑ ↑ ↑ 接缝处约定连续性 次数 20两端失控 次数永远是 3值域有界高次多项式三次样条提高精度的手段升次加段次数跟着涨钉死在 3值域指数膨胀有界改一个控制点整条曲线变形只影响邻近两段次数钉在 3振荡的根源就掐住了——一段三次曲线最多两个拐点翻不起浪来。想更贴合数据就切得更碎但每段仍然是低次的。而且白拿了局部性改一个控制点只影响周围。这对关卡编辑几乎是刚需——挪一下第三个航点不希望第十个航点也跟着跑。代价是你从此得关心接缝得决定那里做到 C¹ 还是 C²。但这笔交易很划算把一个全局的、指数爆炸的问题换成了一堆局部的、可精确控制的接缝条件。收束真实函数被锁在[0.038, 1][0.038,\ 1][0.038,1]里。等间距高次插值穿过了每一个采样点却在点与点之间跑到了±60\pm 60±60甚至更远——给出了理论上不可能的答案。三条实用结论一别只检查采样点。龙格现象在采样点上误差为零任何只看节点的验证都会放过它。检查值域min/max是最廉价的拦网。二画图时固定 y 轴并标出合法值域。换尺度的图会同时掩盖和夸大问题。三不要用一条高次曲线穿过所有航点用分段三次样条。最后一条不是样条更简单所以用样条而是高次多项式在这个场景下真的会坏掉而且点越多坏得越厉害——恰好和直觉相反。想要更精确不是升次是分段。