Поиск пересечения между двумя функциями с использованием Matlab или 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; но это ничего не изменило. Как я могу заставить его возвращать мне значения пересечения?

Спасибо.


person Matheus Danella    schedule 18.06.2016    source источник
comment
Да, забыл добавить, что эти две функции имеют три точки пересечения на выбранном интервале.   -  person Matheus Danella    schedule 19.06.2016
comment
Я добавил ответ, чтобы показать, как следует решать такую ​​числовую проблему.   -  person Andras Deak    schedule 19.06.2016


Ответы (3)


Вы должны помнить, что Matlab используется для поиска численных решений задач. Вы предоставляете дискретный набор входных точек x=0:0.001:5; и просите его вычислить дискретные выходные точки y1[x] и y2[x]. Это означает, что y1 и y2 не являются непрерывными и не обязательно пересекаются, как это делают их непрерывные аналоги. У меня нет Matlab, поэтому я не запускал ваш код, но ваши дискретные функции, скорее всего, не пересекаются. То есть нет пары точек a = y1[x_i] и b = y2[x_i], где a = b. Вместо этого вы, скорее всего, захотите найти точки, в которых y2-y1 находится по одну сторону от нуля для определенного входа и по другую сторону от нуля для следующего входа. Это означало бы, что непрерывные аналоги функции пересекались бы где-то посередине.

Случай, когда функции встречаются, но не пересекаются, немного сложнее, но идея та же.

РЕДАКТИРОВАТЬ:

Такого рода вещи легче всего представить с помощью изображения, поэтому я создал одно, иллюстрирующее то, что я имею в виду.

График y1 и y2

Здесь я использовал гораздо меньше точек, чем вы пытаетесь использовать, но идея та же. Вы можете видеть, что непрерывные версии y1 и y2 пересекаются в нескольких местах, но вы просите Matlab найти точку в y1, которая равна точке в y2 для идентичных значений x. На этом изображении вы можете видеть, что многие из них близки, но ваш компьютер хранит числа с плавающей запятой с очень высокой точностью, поэтому шансы на то, что они на самом деле равны, очень малы.

Когда вы увеличиваете количество точек выборки, изображение начинает больше походить на его непрерывный аналог.

Изображение с увеличенным количеством точек выборки

person user2027202827    schedule 18.06.2016

Два существующих ответа объясняют, почему вы не можете так легко найти точное пересечение. Но что вам действительно нужно, так это ответ на вопрос что делать вместо этого, чтобы получить точные пересечения?

В вашем конкретном случае вы знаете аналитические функции, пересечение которых вы хотите выяснить. Вы можете использовать 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. Если вы подозреваете, как выглядят ваши функции, это вовсе не безнадежно.

Так что же произойдет, если ваши функции станут более беспорядочными? В общем случае вы можете использовать функцию интерполяции, чтобы играть роль y1fun и y2fun в приведенном выше примере, например, используя 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. Тщательно выбирая начальные точки, вы сможете найти все нули как можно точнее.

person Andras Deak    schedule 18.06.2016

Возможно, два вектора нигде не имеют точно равных значений. Вы можете попытаться найти наименьшую разницу:

abs(y1-y2)<tolerance

где допуск=0,001 — небольшое число

person Airidas Korolkovas    schedule 18.06.2016