牛顿迭代法自定义函数陷入死循环无输出,求代码排查
牛顿迭代法死循环与变量问题排查
核心问题分析
死循环根源
原代码的循环条件while np.absolute(xi_1) > min完全错误。牛顿迭代的终止逻辑应该是当前点的函数值足够接近0(说明找到根),或者两次迭代的差值足够小。而你判断的是迭代点本身的绝对值,目标函数的根在1.3左右,这个值的绝对值远大于1e-6,所以循环永远不会停止。eval的不合理使用
用字符串传递函数再通过eval执行的方式,不仅存在安全风险,还容易引发变量作用域问题(之前的变量未定义报错就是这个原因)。直接传递函数对象是更简单可靠的方式。其他细节问题
- 硬编码初始猜测值
guess=2,忽略了调用时传入的参数,逻辑冗余 - 数值微分步长0.01过大,导数计算精度不足,可能影响迭代收敛
- 没有处理导数接近0的情况,可能导致除以0报错
修正后的代码实现
牛顿迭代函数
import numpy as np def fnewton(func, df_func, initial_guess, tol=1e-6): xi_1 = initial_guess n = 0 # 终止条件:函数值绝对值小于设定的容差 while np.abs(func(xi_1)) > tol: n += 1 df_val = df_func(xi_1) # 避免导数为0导致除以0错误 if np.abs(df_val) < 1e-10: raise ValueError("导数接近0,无法继续迭代") # 牛顿迭代公式 x = xi_1 - func(xi_1) / df_val xi_1 = x print(f"根的位置:{x}") print(f"迭代次数:{n}") return x
目标函数与导数函数
def a(x): return np.exp(np.exp(-x)) - x**2 + x def dadx(x): h = 1e-4 # 缩小步长提升数值微分精度 return (a(x + h) - a(x)) / h
调用方式
fnewton(a, dadx, 2)
修改说明
- 移除
eval,直接传递函数对象,彻底解决变量作用域问题 - 修正循环终止条件为判断函数值绝对值,符合牛顿迭代的收敛逻辑
- 增加导数接近0的判断,避免运行时错误
- 使用传入的初始值作为迭代起点,逻辑更合理
- 缩小数值微分步长,提升导数计算的准确性
内容的提问来源于stack exchange,提问作者afg
相关产品推荐
相关产品推荐

