如何通过pytest测试?一阶/二阶导数计算误差问题的修改方案
解决导数计算的pytest测试问题
首先得搞清楚,你用的中心差分法误差来自两方面:截断误差(泰勒展开近似带来的,阶数是O(h²))和舍入误差(浮点数精度限制导致的,h太小的时候,f(x+h)和f(x-h)的差值会因为精度丢失而失真)。你当前的h取值要么过小(一阶导数的1e-10)要么不够最优(二阶导数的1e-4),才导致误差达不到测试要求。
具体修改方案
- 一阶导数的中心差分:把h调整为
1e-5(双精度浮点数下的最优h区间),这个值能平衡截断和舍入误差,让误差降到1e-13以下。 - 二阶导数的中心差分:把h调整为
1e-6,可以把误差控制在1e-14以内。
修改后的代码示例
def error_5_1_11(x): def f(x): return x ** 3 - 0.3 * x ** 2 - 8.56 * x + 8.448 def f_1(f, x, h=1e-5): # 调整h到1e-5 return (f(x + h) - f(x - h)) / (2 * h) def f_2(f, x, h=1e-6): # 调整h到1e-6 return (f(x + h) - 2 * f(x) + f(x - h)) / h ** 2 return f_1(f, x)-(-8.56), f_2(f, x)-(-0.6)
为什么这样调整?
- 当h取
1e-10时,x+h和x在双精度浮点数里几乎没法区分(双精度精度约为1e-16),计算f(x+h)-f(x-h)时会丢失大量有效数字,舍入误差暴增,结果反而偏离真实值。 - 二阶导数用
1e-4时,截断误差还不够小,调到1e-6后,截断误差和舍入误差都能被控制在测试要求的范围内。
另外,也可以改用更贴合数值计算的断言方式(可选),比如用numpy.allclose替代直接判断绝对值:
def test_error(): a, b = error_5_1_11(0) assert allclose(a, 0, atol=1e-13) and allclose(b, 0, atol=1e-14)
不过只要调整好h的值,原测试也能顺利通过。
内容的提问来源于stack exchange,提问作者Ziming Wang
相关产品推荐
相关产品推荐

