Задача. Метод Эйткена-Стеффенсона (развитие метода простой итерации). Найти решение уравнения [latex]x=\varphi(x)[/latex] методом Эйткена-Стеффенсона, в котором от заданного начального [latex]x_{0}[/latex] три очередных приближения находятся по формулам: [latex]x_{n+1}=\varphi (x_{n})[/latex]; [latex]x_{n+2}=\varphi (x_{n+1})[/latex]; [latex]x_{n+3}=\frac{x_{n}x_{n+2}-x_{n+1}^{2}}{x_{n}-2x_{n+1}+x_{n+2}}[/latex]. Процесс продолжается до достижения одного из условий: [latex]\left | x_{n+3}-x_{n+2} \right |<\varepsilon[/latex] или [latex]x_{n}-2x_{n+1}+x_{n+2}=0[/latex].
Решение. В начале мы задаем начальное приближение [latex]x=x_{0}[/latex] и [latex]\varepsilon[/latex]. Нам понадобится цикл с постусловием. Далее вычисляем первое приближение [latex]x_{1}=\varphi (x_{0})[/latex] и второе приближение [latex]x_{2}=\varphi (x_{1})[/latex]. Находим по формуле [latex]x=\frac{x_{0}x_{2}-x_{1}^{2}}{x_{0}-2x_{1}+x_{2}}[/latex]. Далее мы проверяем выполнение условия выхода из цикла: если [latex]\left | x-x_{0} \right |>\varepsilon[/latex] (нужно проверять разность [latex]\left | x-x_{0} \right |>\varepsilon[/latex], а не [latex]\left | x-x_{2} \right |>\varepsilon[/latex]) и [latex]x_{0}-2x_{1}+x_{2}\neq 0[/latex] тогда цикл продолжается, но если хотя бы одно из условий выполнено, то мы получаем, что [latex]x[/latex] — решение уравнения [latex]x=\varphi(x)[/latex].
Данная программа написана для функции [latex]9.2x^{3}+3.3x^{2}+4x-1[/latex].
Тесты:
x | [latex]\varepsilon[/latex] | Корень уравнения | Комментарий |
2 | 0.005 | 1.99889 | Пройден |
1 | 0.00002 | 0.233905 | Пройден |
-4 | 0.0005 | -3.99981 | Пройден |
Код программы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <iostream> #include <math.h> using namespace std; double f(double x) { return 9.2*x*x*x+3.3*x*x+4*x-1; //задаем уравнение } double es(double x, double eps) //с помощью метода Эйтнена-Стеффенсона считаем приближения { double x0, x1, x2, d; do { x0=x; x1=f(x0); x2=f(x1); d=x0-2*x1+x2; if (d!=0) { x=(x0*x2-x1*x1)/d; } else return x; } while(fabs(x-x0)>eps); //условие окончания подсчета return x; } int main() { double x, eps; cin >> x >> eps; cout << es(x, eps); return 0; } |
Код программы можно проверить здесь.
Решение на Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import java.util.*; import java.lang.*; import java.io.*; class Ideone { static double f(double x) { return 9.2*x*x*x+3.3*x*x+4*x-1; } public static void main (String[] args) throws java.lang.Exception { Scanner in = new Scanner(System.in); double x, eps, x0, x1, x2, d; x = in.nextDouble(); eps = in.nextDouble(); do{ x0=x; x1=f(x0); x2=f(x1); d=x0-2*x1+x2; if (d!=0) { x=(x0*x2-x1*x1)/d; } else break; } while(Math.abs(x-x0)>eps); System.out.print(x+" "); } } |
Как Вы думаете зачем указано условие продолжения «или x_{n}-2x_{n+1}+x_{n+2}=0.»? Т.е. в Ваших обозначениях это d!=0. Дело в том, что при вычислении x_{n+3}=\frac{x_{n}x_{n+2}-x_{n+1}^{2}}{x_{n}-2x_{n+1}+x_{n+2}} происходит деление на это выражение, и чтобы избежать деления на ноль, процесс мы заканчиваем (ответом видимо будет x_{n+2}). А Вы таки делите на 0, заканчиваете вычисления и ответом предоставляете результат деления на 0 — плохо.
Кроме того первое из условий продолжения \left | x_{n+3}-x_{n+2} \right |<\varepsilon, а не \left | x_{n+3}-x_{n} \right |<\varepsilon - т.е. в Вашем случае мне непонятно почему Вы пишете "(нужно проверять разность \left | x-x_{0} \right |>\varepsilon, а не \left | x-x_{2} \right |>\varepsilon)» — хотя вполне возможно правы Вы, а не Юркин — попробовал найти информацию в Интернет, ее мало и она скорее с форумов и методичек в основном. Если Вы действительно правы, а не Юркин сошлитесь на авторитетный источник — откуда Вы взяли эту информацию.
А где результаты выполнения программы? Т.е. таблица тестов? Ее нет вообще… на ideone непоказательный тест (с большим eps).
Я прочла объяснение этого метода вот здесь: http://www.ppent.samsu.ru/docs/num_met_for_fiz_3.pdf , начиная со страницы 16 и, если я правильно поняла, то нужна именно разность [latex]\left | x-x_{0} \right |>\varepsilon[/latex]
Какой-то слишком фундаментальный источник для меня, долго разбираться. Но думаю, что Вы правы. Большое спасибо за ссылку.
Исправила, деления на ноль не будет больше и добавила тесты
Все конечно хорошо, но уравнение 9.2*x*x*x+3.3*x*x+4*x-1 = x имеет один действительный корень 0.233905, который Вы и нашли. Видимо, при x=2 и x=4 не выполняются условия применимости метода — желательно указать в отчете.
Засчитано, 8 баллов (октябрьское задание).
Java версия засчитана, 5 баллов — увы, просрочено.