如题,Newton迭代为常见的非线性方程的解法,迭代形式为x1 = x-(newton(x)./diff(newton(x))),即第k个x减去f/f'
算法的实现较为容易,但实际编写代码时出现了一个小问题:对表达式求导后代入初始值
提前写出原表达式与其求导形式再进行替换固然可行,但有些麻烦,不方便更改
一开始选用subs来整体替换,但之后发现这样会使得计算量变得极其庞大。

问题出在sym表达式代入数值后得到的解是精确解,或者说一组符号。在进行运算时它们才会自动转换为数值。但我们其实并不需要如此精确的分数形式的解。于是决定提前算出导数在初始解下的值并使用roundn保留9位小数,但这样又会出现报错

于是搜索发现vpa能完美解决该问题,附上大佬的帖子
https://blog.csdn.net/Davidietop/article/details/105364792
又在函数体中尝试了许久,终于得到了解决,留下了感动的泪水。顺带一提,与C++不同,matlab中变量的值好像不能反复改动,比如使用y=vpa(y,9)时结果较之前没有丝毫改变,必须在第一次计算y时就使用vpa。

附上代码
function f = equation(x)
f = x.^3-x-1;%这里题目要求的是这个方程,也可改为自行输入
end
function y = newton(x)
syms a;
f1 = diff(equation(a));%存放导数形式
b=vpa(subs(f1,a,x),9);%代入x算出数值,保留9位有效数字
y=vpa(x-equation(x)./b,9);
end
x=input('x=');%输入初值
eps=input('eps=');%误差限
inff=input('解的容许下界为:');
supp=input('解的容许上界为:');
x1=1;%判断是否到达所需精度
count = 0;
while (x1>eps)
xb=x;
x=newton(xb);
x1=vpa(abs(x-xb),9);
count=count+1;
end
if(x>supp||x<inff)
disp('在给定区间内找不到合适的解');
else
disp('符合精度的解为: ');
fprintf('%.6f',x)
disp('迭代次数为:');
disp(count);
end