function root = ridders_method(func, left, right, tol, max_iter,interpolation_method)
% func: 待求函数
% a, b: 初始区间
% tol: 允许误差
% max_iter: 最大迭代次数
%inter_mod: 插值方法
f_left = feval(func, left);
f_right = feval(func, right);
%判断端值
if f_left * f_right > 0
error('区间端点处的函数值符号必须相反。');
end
%开始迭代
for k = 1:max_iter
%计算区间中点和对应的函数值
mid = (left + right) / 2;
f_mid = feval(func, mid);
if strcmp(interpolation_method, 'line')
%线性插值, 计算d处函数值和其位置
d = mid + (mid - left) * sign(f_left - f_right) * f_mid / sqrt(f_mid^2 - f_left * f_right);
%二次多项式插值
elseif strcmp(interpolation_method, 'polyfit')
square = polyfit([left mid right],[f_left f_mid f_right],2);
d = roots(square);%多项式的根
d = d(imag(d) == 0);%保留实数根
d = d(d >= left & d <= right);%保留在当前区间内的根
%判断d是否为空
if isempty(d)
error('未找到实数解');
end
% 选择根使得与 c 更近
[~, idx] = min(abs(d - mid));
d = d(idx);
elseif strcmp(interpolation_method, 'spline')
spline_coeffs = spline([left, mid, right], [f_left, f_mid, f_right]);
d = fzero(@(x) ppval(spline_coeffs, x), mid);
else
error('不是选定的插值方法');
end
fd = feval(func, d);%计算根(可能)在该函数的值
%判断是否找到根
if fd == 0 || ((right - left)/2) < tol
root = d;
return;
end
%更新端点
if f_left * fd < 0
right = d;
f_right = fd;
else
left = d;
f_left = fd;
end
%判断收敛条件
if abs(right - left) < tol
root = (left + right) / 2;
return;
end
end
%若不满足其要求,并给出原因
error('Ridders方法未在最大迭代次数内收敛。');
end
%复制到新脚本
% %%简单样例:
% % func: 待求解的函数句柄
% % a, b: 初始区间
% % tol: 允许误差
% %max_iter: 最大迭代次数
% %interpolation_method:插值方法
% func = @(x) x^2 - 2;
% a = 0;
% b = 2;
% tol = 1e-12;
% max_iter = 1000;
% interpolation_method = 'spline'; % 可以选择 'line', 'polyfit'(2次), 'spline'(三次样条)
%
% root = ridders_method(func, a, b, tol, max_iter, interpolation_method);
% disp(['Root: ', num2str(root)]);
实现代码如上