使用Matlab或Scilab查找两个函数之间的交集

时间:2016-06-18 21:43:52

标签: matlab function intersection scilab

我这样做:

>> plot(x,y1,x,y2);
>> x=0:0.001:5;
>> y1=sin(x)+cos(1+x.^2)-1;
>> y2 = ((1/2).*x)-1;
>> find (y1==y2)

得到这个:

ans =

   Empty matrix: 1-by-0

作为一个答案,它只是让我发疯!我不知道为什么Matlab和Scilab没有给我相交的答案。我一直试图使间隔变小,如x = 0:0.0001:5;但它没有改变任何东西。如何让它返回交叉点值?

谢谢。

3 个答案:

答案 0 :(得分:1)

你必须记住Matlab用于找到问题的数值解法。您提供了一组离散的输入点x=0:0.001:5;,并要求它计算离散输出点y1[x]y2[x]。这意味着y1y2不是连续的,并且不一定像它们的连续对应物那样相交。我没有Matlab,所以我没有运行你的代码,但是你的离散函数很可能不会出现问题。也就是说,a = y1[x_i]b = y2[x_i]没有一对a = b。相反,您最想要做的是查找y2-y1在特定输入处为零的一侧的点,以及在下一次输入的零的另一侧。这意味着函数的连续conterparts会在两者之间交叉。

函数满足但不交叉的情况稍微有些棘手,但同样的想法。

编辑:

这种事情最容易用图像包裹,所以我创建了一个说明我的意思。

Plot of y1 and y2

在这里,我使用的点少于你想要使用的点数,但这个想法是一样的。您可以看到y1和y2的连续版本在几个地方交叉,但是您要求matlab做的是在y1中找到一个点,该点等于y2中相同x值的点。在这张图片中你可以看到很多都很接近,但你的计算机存储的浮点数非常高,所以实际上它们相等的可能性非常小。

当您增加采样点数时,图像看起来更像是“连续对应物”。

Image with increased sample points

答案 1 :(得分:1)

现有的两个答案解释了为什么你不能轻易找到一个确切的交叉点。但你真正需要的是回答做什么而不是以获得精确的交叉点?

在您的具体情况下,您知道要想出的交叉点的分析函数。您可以使用fzero和(可选的匿名)函数来查找由两个原始函数的差异定义的函数的零:

y1fun = @(x) sin(x)+cos(1+x.^2)-1;
y2fun = @(x) ((1/2).*x)-1;
diff_fun = @(x) y1fun(x)-y2fun(x);
x0 = 1; % starting point for fzero's zero search
x_cross = fzero(diff_fun,x0);

现在,这将为您提供差异函数的一个零,即一个的函数交集。事实证明,找到函数的每个零是一项具有挑战性的任务。通常,您必须使用各种起点fzero多次致电x0。如果你怀疑你的功能是什么样的,那就完全没有希望了。

那么如果你的功能更乱,会发生什么?在一般情况下,您可以使用插值函数在上面的示例中播放y1funy2fun的部分,例如使用interp1

% generate data
xdata = 0:0.001:5;
y1data = sin(xdata)+cos(1+xdata.^2)-1;
y2data = ((1/2).*xdata)-1;

y1fun = @(x) interp1(xdata,y1data,x);
y2fun = @(x) interp1(xdata,y2data,x);
x0 = 1; % starting point for fzero's zero search
x_cross = fzero(@(x)y1fun(x)-y2fun(x),x0);

这导致了原来的问题。请注意,interp1默认情况下使用线性插值,具体取决于您的函数的外观以及数据的散布方式,您可以选择其他选项。还要注意外推的选项(要避免)。

因此,在这两种情况下,每次拨打fzero都会得到一个交叉点。通过仔细选择起点,您应该能够尽可能准确地找到所有零点。

答案 2 :(得分:0)

也许这两个向量在任何地方都没有完全相等的值。您可以尝试搜索最小的差异:

abs(y1-y2)<tolerance

其中公差= 0.001是一个小数