Метод секущих для e^(x) matlab

Я пытаюсь закодировать метод секущих для f(x)=e^(-x)-sin(x), чтобы найти наименьший положительный корень. Мой код, кажется, получает ошибку.

%// Initial values and tolerance
x(0) = 2;
x(1) = 10;
f = @(x) exp(-x)-sin(x);

error = 0.001;

%// Different iterations
for k=0:100

    x(k+1) = x(k) - (f(x(k)))*((x(k) - x(k-1))/(f(x(k)) - f(x(k-1))));

    if abs(x(k)-x(k-1)) < error
        return;
    end
end

person user1979029    schedule 02.03.2016    source источник
comment
при k = 0 x (k-1) равно x (-1), цикл for не должен начинаться с 1.   -  person chiliNUT    schedule 02.03.2016
comment
ну, вы не можете получить доступ к x(0) в Matlab, так что это должно начинаться с 2   -  person R.Falque    schedule 02.03.2016


Ответы (1)


Почему ошибка?

Как отмечено в комментариях к вашему вопросу, vector(1D matrix ) индексы в Matlab работают от 1 до end, поэтому в вашем случае вы пытаетесь получить доступ к недопустимым индексам в разных местах вашего кода:

%// Initial values and tolerance
x(0) = 2;                         %// <-- invalid index
x(1) = 10;
f = @(x) exp(-x)-sin(x);

error = 0.001;

%// Different iterations
for k=0:100
                     %// for k=0: x(k) and x(k-1) both invalid indices
                     %// for k=1: x(k-1) invalid index
    x(k+1) = x(k) - (f(x(k)))*((x(k) - x(k-1))/(f(x(k)) - f(x(k-1))));

    if abs(x(k)-x(k-1)) < error
        return;
    end
end

Исправленный код

Мы исправляем недопустимые случаи индекса выше (изменив также ваш цикл for на цикл while):

%// Function to (attempt) to find a root to
f = @(x) exp(-x)-sin(x);

%// Initial values and tolerance
x(1) = 2;
x(2) = 10;
error = 0.001;

%// Different iterations
k=2;
maxIt = 100;
while (abs(x(k)-x(k-1)) > error) && (k-1 <= maxIt)
    x(k+1) = x(k) - f(x(k))*(x(k) - x(k-1))/(f(x(k)) - f(x(k-1)));
    k = k + 1;
end

%// print result
disp(['x(end) = ' num2str(x(end)) ...
  ', f(x(end)) = ' num2str(f(x(end))) ...
  ', iterations: ' num2str(k-2)]);

Получение результата

x(end) = 6.285, f(x(end)) = -4.9315e-10, iterations: 7
person dfrib    schedule 02.03.2016
comment
Я не думаю, что изменение с for на while улучшит ситуацию. Это фантазия напрасно, хотя я понимаю, почему вы ее используете. - person R.Falque; 02.03.2016
comment
@R.Bergamote Поскольку я включил итератор k в инвариант выражения/сигнатуры цикла while, я бы сказал, что это дело вкуса, поскольку в этом случае два варианта цикла очень похожи. Однако важно, что вы указываете, что цикл while никоим образом не делает его лучше (о чем я прямо не заявлял; однако я понимаю, что такое утверждение может быть выведено читателем из вышеизложенного). Спасибо за ваш отзыв. - person dfrib; 02.03.2016
comment
С точки зрения кода это точно так же, однако я бы не рекомендовал его для отладки и понимания кода. В противном случае это действительно правильный метод - person R.Falque; 02.03.2016
comment
как найти наименьший положительный корень? - person user1979029; 02.03.2016
comment
Я попробовал допуск с 0,0001, но я продолжал получать высокий корень? Я делаю что-то неправильно? - person user1979029; 02.03.2016
comment
@user1979029 user1979029 Поскольку ваша функция имеет несколько корней (и метод в лучшем случае находит только один из них), вам придется настроить начальные значения, а не допуск. Попробуйте, например. x(1) = 0, x(2) = 2. - person dfrib; 02.03.2016
comment
О, я хотел, чтобы допуск был 0,0001. Извините за путаницу! Я получаю: x(конец) = 34,5575, f(x(конец)) = -3,9184e-15, итераций: 8. И этот корень слишком велик. Я знаю, что он должен быть около 0,58. Я чувствую, что делаю какую-то ошибку. - person user1979029; 02.03.2016
comment
Пробовали ли вы приведенный выше код с изменениями начальных значений, x(1) = 0 и x(2) = 2 (и допуском по вашему желанию)? Используя это сам, скрипт создает корень x(end) = 0.58853. - person dfrib; 02.03.2016