我有一个Matlab项目,我需要在其中创建一个从用户接收两个数学函数的GUI。然后我需要找到它们的交点,然后绘制两个函数。
所以,我有几个问题:
您知道我可以使用哪种算法来查找交叉点吗?当然我更喜欢我已经可以在互联网上找到一个Matlab代码。而且,我更喜欢它不会是Newton-Raphson方法。 我应该指出我不允许使用内置的Matlab函数。
我无法绘制功能。我基本上做的是:
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
cla % To clear axes when plotting new functions
ezplot(fun_f);
hold on
ezplot(fun_g);
axis ([-20 20 -10 10]);
问题在于,有时,轴限制不允许我看到其他功能。这将发生,例如,如果我将一个函数设为log10(x)
而另一个函数设为y=1
,则y=1
将不会显示。
我已经尝试过使用所有轴命令,但无济于事。如果我自己设置限制,则功能仅存在于某些限制内。我不明白为什么。
3。如何在静态文本中显示数字?或者更好的是,用数字串?
我希望显示类似x0 = [root1]; x1 = [root2]
的内容。我发现的唯一解决方案是将我发现的根变成字符串,但我不愿意。
至于方程求解器,这是我到目前为止的代码。我知道这是非常业余的,但它似乎是最直接的"办法。另外请记住,它还没有完成(例如,它只会向我显示两个解决方案,我不太确定如何在一个静态文本中显示多个根,因为它们是字符串,因此问题#3)。
function [Sol] = SolveEquation(handles)
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
f = inline(fun_f);
g = inline(fun_g);
i = 1;
Sol = 0;
for x = -10:0.1:10;
if (g(x) - f(x)) >= 0 && (g(x) - f(x)) < 0.01
Sol(i) = x;
i = i + 1;
end
end
solution1 = num2str(Sol(1));
solution2 = num2str(Sol(2));
set(handles.roots1,'string',solution1);
set(handles.roots2,'string',solution2);
if
条件是因为减法永远不会给我一个绝对零,这似乎有点解决它,虽然它真的不完美,有时它会给我两个以上非常相似解决方案(例如1.9和2)。
x
的范围是任意的,由我选择。
我知道这是一个很长的问题,所以我非常感谢你的耐心等待。 非常感谢你提前!
答案 0 :(得分:1)
问题1
我认为这是一种更强大的方法,用于在离散点处查找给定数据的根。寻找函数之间的差异何时改变符号,这对应于它们越过。
S=sign(g(x)-f(x));
h=find(diff(S)~=0)
Sol=x(h);
如果您可以根据需要评估功能,可以使用更多方法,但这取决于域的大小以及您想要的最佳效果。例如,如果您不需要很高的准确度,那么您的f
和g
功能很容易计算,而且您无法或不想要使用衍生物,您可以使用与第一个代码片段相同的想法获得更准确的根,但是迭代地执行:
G=inline('sin(x)');
F=inline('1');
g=vectorize(G);
f=vectorize(F);
tol=1e-9;
tic()
x = -2*pi:.001:pi;
S=sign(g(x)-f(x));
h=find(diff(S)~=0); % Find where two lines cross over
Sol=zeros(size(h));
Err=zeros(size(h));
if ~isempty(h) % There are some cross-over points
for i=1:length(h) % For each point, improve the approximation
xN=x(h(i):h(i)+1);
err=1;
while(abs(err)>tol) % Iteratively improve aproximation
S=sign(g(xN)-f(xN));
hF=find(diff(S)~=0);
xN=xN(hF:hF+1);
[~,I]=min(abs(f(xN)-g(xN)));
xG=xN(I);
err=f(xG)-g(xG);
xN=linspace(xN(1),xN(2),15);
end
Sol(i)=xG;
Err(i)=f(xG)-g(xG);
end
else % No crossover points - lines could meet at tangents
[h,I]=findpeaks(-abs(g(x)-f(x)));
Sol=x(I(abs(f(x(I))-g(x(I)))<1e-5));
Err=f(Sol)-g(Sol)
end
% We also have to check each endpoint
if abs(f(x(end))-g(x(end)))<tol && abs(Sol(end)-x(end))>1e-12
Sol=[Sol x(end)];
Err=[Err g(x(end))-f(x(end))];
end
if abs(f(x(1))-g(x(1)))<tol && abs(Sol(1)-x(1))>1e-12
Sol=[x(1) Sol];
Err=[g(x(1))-f(x(1)) Err];
end
toc()
Sol
Err
这将&#34; zoom&#34;进入每个疑似根周围的区域,并反复提高准确性。您可以调整参数以查看它们是否提供更好的行为(容差tol
,15,要生成的新点数,可能更高)。
问题2
您可能最好避免ezplot
,并使用plot
,这可以让您获得更好的控制权。您可以使用内联函数进行矢量化,以便像匿名函数一样对它们进行评估,就像我在前面的代码片段中所做的那样,使用
f=inline('x^2')
F=vectorize(f)
F(1:5)
这应该使绘图更容易:
plot(x,f(x),'b',Sol,f(Sol),'ro',x,g(x),'k',Sol,G(Sol),'ro')
问题3
我不确定你为什么不想把你的根源显示为字符串,这有什么不对:
text(xPos,yPos,['x0=' num2str(Sol(1))]);