如何传递函数作为参数?牛顿法求π遇索引越界错误求助
问题分析与修正方案
原代码核心错误点
- 参数传递错误:调用
newton(3,math.sin(3),0.000001)时,第二个参数传的是math.sin(3)的计算结果(数值),但需要传入的是函数对象math.sin。 - 循环条件逻辑颠倒:原代码
while abs(A[n]-A[n-1])<=err,意思是误差达标后仍继续迭代,完全搞反逻辑,应该是误差大于允许值时才继续迭代。 - 列表索引越界:初始
A = [x0],n=1时直接访问A[n](即A[1]),但此时列表仅1个元素,必然触发IndexError。 - 错误的函数调用:
math.f(x0)是错误写法,math模块不存在f函数,应直接使用传入的函数参数f。 - 冗余递归逻辑:牛顿法是迭代算法,无需递归调用自身,原else分支的递归完全错误,会导致逻辑混乱。
- 导数实现低效:原
deriv返回lambda的写法冗余,且单侧差分精度较低。
修正后的代码
import math # 数值求导:用中心差分计算f在x点的导数值,精度更高 def deriv(f, x): h = 1e-5 return (f(x + h) - f(x - h)) / (2 * h) def newton(x0, f, err): A = [x0] while True: # 取当前迭代的最后一个值计算 current_x = A[-1] fx = f(current_x) fpx = deriv(f, current_x) # 牛顿迭代公式 next_x = current_x - fx / fpx A.append(next_x) # 误差达标则终止迭代 if abs(next_x - current_x) <= err: break return A, A[-1] # 求π的近似值:sin(π)=0,找sin(x)=0在x=3附近的根 approximations, pi_approx = newton(3, math.sin, 1e-6) print("迭代过程:", approximations) print("π的近似值:", pi_approx)
关键修改说明
- 导数函数改为直接返回当前点的导数值,用中心差分替代单侧差分,精度提升。
- 迭代逻辑改为基于列表最后一个元素计算,彻底避免索引越界问题。
- 移除冗余的lambda和递归写法,逻辑更简洁直观。
- 修正参数传递,传入
math.sin函数对象而非数值。 - 循环条件改为当迭代误差小于等于允许值时终止,符合牛顿法迭代终止逻辑。
内容的提问来源于stack exchange,提问作者user996159
相关产品推荐
相关产品推荐

