R语言牛顿法求根时while循环出现缺失值错误的求助
问题分析与修复方案
核心问题拆解
- 报错直接诱因:你运行的代码中while循环包含
iter < max_iter判断,但未定义max_iter变量/参数,导致该比较返回NA,整个循环条件因混合TRUE/FALSE与NA触发"missing value where TRUE/FALSE needed"错误。 - 算法本质缺陷:目标函数
g(x) = x/sqrt(1+x²)的牛顿迭代公式可简化为x_{n+1} = -x_n³:- 当
|x₀| < 1时,迭代值会向0收敛; - 当
|x₀| = 1时,迭代会在1和-1之间无限震荡; - 当
|x₀| > 1时,迭代值绝对值会指数级增大(如x₀=2→x₁=-8→x₂=512→...),完全发散,永远无法满足收敛条件。
- 当
修复后的完整代码
g_x <- function(x){ return(x/(1+x^2)^(1/2)) } dg_x <- function(x){ # 目标函数的导数计算 return(1/(x^2+1)^(3/2)) } newton <- function(x_0, k, max_iter = 100){ # 参数说明: # x_0: 初始猜测值 # k: 容差参数,容差为10^(-k) # max_iter: 最大迭代次数,默认100 tol <- 10^(-k) # 替换dplyr::between为原生逻辑判断,摆脱包依赖 if(g_x(x_0) >= -tol/2 && g_x(x_0) <= tol/2){ return(c(x_0, 0)) } iter <- 1 x_prev_prev <- x_0 # 记录前前次迭代值,用于检测震荡 x_1 <- x_0 - (g_x(x_0)/dg_x(x_0)) while(abs(x_1 - x_0) > tol && iter < max_iter){ # 检测发散:迭代值超出合理范围时提前终止 if(abs(x_1) > 1e10){ warning("迭代发散,无法收敛到根") return(c(NA, iter)) } # 检测震荡:针对当前函数的特殊迭代规律(1↔-1循环) if(abs(x_1 + x_prev_prev) < tol){ warning("迭代进入震荡循环,无法收敛到根") return(c(NA, iter)) } x_prev_prev <- x_0 x_0 <- x_1 x_1 <- x_0 - (g_x(x_0)/dg_x(x_0)) iter <- iter + 1 } # 判断终止原因:收敛/达到最大迭代次数 if(iter >= max_iter){ warning("达到最大迭代次数,未收敛") return(c((x_1+x_0)/2, iter)) } return(c((x_1+x_0)/2, iter)) }
关键修复点说明
- 补全迭代次数控制:新增
max_iter参数并设置默认值,避免未定义变量导致的NA判断; - 移除外部包依赖:用原生逻辑判断替换
between函数,避免因未加载dplyr包产生的隐性错误; - 添加发散与震荡检测:提前识别无法收敛的情况,避免无限循环或数值溢出;
- 明确终止原因:通过警告信息区分"发散"、"震荡"、"达到最大迭代次数"三种非收敛场景,提升调试效率。
内容的提问来源于stack exchange,提问作者Chance Law
相关产品推荐
相关产品推荐

