1. 课程导入与数值算法测试概览
数值算法是科学计算、工程仿真、机器学习与金融定价等领域的共同底座。它不像普通业务代码那样只关心“输入是否得到预期输出”,而是要在浮点数的有限精度下,处理舍入误差、截断误差、条件数放大、迭代收敛性等一系列连续数学问题。因此,数值算法的测试与验证,本质上是在“离散的、有误差的计算世界”里,判断一个算法是否可靠地逼近了它声称要解决的数学问题。
数值算法测试的特殊性
先看一个具体例子。假设我们实现一个求解线性方程组 Ax=b 的高斯消元程序,取 A=[[1,1],[1,1+1e-16]],b=[2,2]。从数学上看,该矩阵接近奇异,解对扰动极其敏感。若在双精度下直接消元,主元 1e-16 会带来巨大的舍入放大,得到的解可能与真实解相差甚远;而若采用列主元消元,结果会稳定得多。这说明:同一个算法逻辑,在不同的数值路径下可能给出完全不同的可信度。测试不能只比对“答案对不对”,还要考察误差是否在可接受范围内、算法在病态输入下是否退化、迭代是否在有限步内收敛。
数值算法测试的特殊性主要体现在四个方面。第一,正确性不是二值的:浮点运算下几乎不存在“完全相等”,需要引入绝对误差、相对误差、后向误差等度量。第二,输入空间是连续的:无法穷举,只能通过代表性用例、边界用例与随机用例组合覆盖。第三,误差会传播和累积:一个微小的舍入误差经过多步迭代可能被放大,测试需要关注误差增长趋势而非单点结果。第四,算法正确性与实现正确性要分开看:数学推导正确不代表代码正确,代码正确也不代表在病态问题上数值稳定。
正确性验证的基本概念
在数值计算语境下,“正确性验证”通常包含三个层次。其一是结果正确性:对给定输入,输出与参考解的误差是否小于容差。其二是算法正确性:实现是否忠实于所声明的数学方法,例如迭代格式、收敛判据、边界处理是否与设计一致。其三是数值稳定性:在接近奇异、尺度差异大、迭代次数多等情形下,误差是否被控制在合理范围。
与之配套的常用概念包括:参考解(解析解、高精度解或经认证的基准结果)、容差(绝对容差 atol 与相对容差 rtol 的组合)、后向误差(把计算解代回原问题后残差的大小)、条件数(问题本身对扰动的敏感程度)以及收敛阶与收敛速度(迭代法每步误差下降的速率)。一个常见的误区是只设置一个固定的绝对容差,例如统一用 1e-6 判断所有结果;对于量级为 1e-12 的量,这个容差过松,对于量级为 1e12 的量又过严。更合理的做法是采用 |x - x_ref| <= atol + rtol * |x_ref| 形式的混合判据。
测试与验证在算法开发中的位置
测试与验证不是开发完成后的“收尾环节”,而是贯穿算法选型、实现、调优与交付的持续活动。在选型阶段,需要用基准问题比较不同算法的精度与效率;在实现阶段,需要用单元测试锁定每个数学步骤的行为;在调优阶段,需要用回归测试防止优化引入数值退化;在交付阶段,需要用验收测试证明算法在目标问题域内满足精度要求。可以把这一关系理解为:数学推导给出“应该怎样”,测试验证回答“实际是否如此、在什么条件下成立”。
下图展示了数值算法从问题定义到可信交付的验证闭环,以及各环节中测试所承担的角色。
课程整体路线图
本课程围绕“如何为数值算法设计可信的测试用例,并据此完成正确性验证”展开,整体分为五个递进部分。第一部分建立概念基础,包括误差来源、浮点表示、条件数与稳定性,以及测试与验证的基本术语。第二部分进入测试用例设计方法,覆盖解析解构造、制造解方法、边界与病态用例、随机与统计用例,以及容差设定策略。第三部分按算法族展开专项验证,包括线性方程组、特征值、非线性方程求根、数值积分、常微分方程初值与边值问题、插值与拟合、优化算法等,每类算法给出可执行的用例结构与判据。第四部分讨论工程化实践,包括测试框架组织、参考解管理、回归与性能基线、可复现性保障。第五部分通过综合案例,把用例设计、执行、结果判读与缺陷定位串成完整闭环。
学习本课程时,建议始终带着三个问题阅读:这个算法的误差从哪里来?我设计的用例能否暴露这类误差?我用的判据是否与问题尺度匹配?把这三个问题落实到每一类算法、每一个测试用例上,数值算法的正确性验证才会从“看起来对”变成“有依据地可信”。