如何在Matlab中修改牛顿迭代法代码以找出区间内所有根
牛顿-拉夫逊法寻找区间内所有根的修改方案
核心思路
牛顿-拉夫逊法依赖初始猜测值,要覆盖区间[xl,xr]内所有根,核心是在区间内取多个初始点逐一迭代,同时过滤重复收敛的根(相邻初始点可能指向同一个根)。具体步骤:
- 将目标区间拆分为若干等距的初始猜测点
- 对每个初始点单独执行牛顿迭代
- 剔除迭代失败、超出区间的结果,再通过精度阈值去重得到唯一根集合
修改后的完整代码
function [roots, fail_count] = newraphson_all(fun, xl, xr, tol, num_points) % NEWRAPHSON_ALL 用牛顿-拉夫逊法寻找区间[xl,xr]内的所有根 % 输入参数: % fun - 目标函数句柄 % xl, xr - 搜索区间的左右边界 % tol - 收敛精度 % num_points - 区间内采样的初始猜测点数量 % 输出参数: % roots - 找到的所有根(去重后) % fail_count - 迭代失败的初始点数量 % 初始化变量 fail_count = 0; all_candidates = []; h_deriv = 1e-4; % 求导用的步长 max_iter = 10; % 最大迭代次数 % 生成区间内的初始猜测点 x_guesses = linspace(xl, xr, num_points); % 遍历每个初始猜测点执行牛顿迭代 for xg = x_guesses i = 0; check = 1; current_xg = xg; nrfail = 0; while tol < check i = i + 1; % 计算导数和函数值 fp = derivative(fun, current_xg, h_deriv); y = feval(fun, current_xg); % 牛顿迭代公式 xn = current_xg - y / fp; % 检查迭代有效性:避免越界、迭代次数超限、导数接近0 if xn < xl || xn > xr || i > max_iter || abs(fp) < 1e-10 nrfail = 1; break; end % 计算误差(小值用绝对误差,大值用相对误差) if abs(xn) <= 1 check = abs(current_xg - xn); else check = abs(1 - current_xg / xn); end current_xg = xn; end % 迭代成功则记录结果 if nrfail == 0 all_candidates = [all_candidates; current_xg]; else fail_count = fail_count + 1; end end % 去重处理:将精度范围内的重复根合并 if ~isempty(all_candidates) all_candidates = sort(all_candidates); roots = all_candidates(1); for k = 2:length(all_candidates) if abs(all_candidates(k) - roots(end)) > tol roots = [roots; all_candidates(k)]; end end else roots = []; % 未找到任何根时返回空数组 end end
关键修改说明
- 初始点采样:用
linspace生成等距初始点,num_points可根据函数复杂度调整(建议20-50,复杂函数可适当增加) - 去重逻辑:先排序再通过精度阈值过滤重复根,避免不同初始点收敛到同一个根导致结果冗余
- 鲁棒性优化:将导数为0的判断改为
abs(fp) < 1e-10,规避浮点精度误差导致的误判 - 输出适配:原函数仅返回单个根,修改后返回所有根的数组和迭代失败计数,更贴合多根搜索需求
使用示例
针对你提到的目标函数(0.01-1) + x*cot(x),调用方式如下:
% 定义目标函数句柄 fun = @(x) (0.01 - 1) + x*cot(x); % 搜索区间[1, 20],精度1e-6,采样30个初始点 [roots, fails] = newraphson_all(fun, 1, 20, 1e-6, 30); disp('找到的根:'); disp(roots);
内容的提问来源于stack exchange,提问作者cschlum
相关产品推荐
相关产品推荐

