Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Архив1 / docx54 / Отчёт (9)

.docx
Скачиваний:
51
Добавлен:
01.08.2013
Размер:
182.45 Кб
Скачать

Содержание:

  1. Цель работы…………………………………………………………………………………..2

  2. Исходные данные……………………………………………………………………………2

  3. Графическое решение……………………………………………………………………….2

  4. Метод Ньютона………………………………………………………………………………2

    1. Листинг программы (Метод Ньютона)………………………………………………..2

    2. Результат программы (Метод Ньютона)………………………………………………3

  5. Метод простой итерации……………………………………………………………………3

  6. Метод Гаусса-Зейделя………………………………………………………………………6

    1. Листинг программы (Методы простой итерации и Гаусса-Зейделя)………………..8

    2. Результат программы (Методы простой итерации и Гаусса-Зейделя)………………9

  7. Вывод…………………………………………………………………………………………9

  1. Цель работы: С помощью знаний полученных на лекциях решить СНАУ в структуре MS 2008(C++) методом Ньютона, методом простой итерации и методом Гаусса-Зейделя.

  2. Исходные данные:

  1. Графическое решение

A(1,23;0,56), B(0,24;-0,98), C(-1,23;-0,56), B(-0,24;0,98). За начальное приближение берём точку (1,2;0,5) с соответствующими координатами.

  1. Метод Ньютона

    1. Листинг программы (метод Ньютона):

#include <stdafx.h>

#include <iostream>

#include <math.h>

#include <conio.h>

#include <locale>

using namespace std;

double F(double x, double y)

{

return tan(x*y+0.3)-x*x;

}

double G(double x, double y)

{

return 0.9*x*x + 2*y*y - 2;

}

double dFdX(double x, double y)

{

return y/pow(cos(x*y+0.3), 2)-2*x;

}

double dFdY(double x, double y)

{

return x/pow(cos(x*y+0.3), 2);

}

double dGdX(double x, double y)

{

return 1.8*x;

}

double dGdY(double x, double y)

{

return 4*y;

}

int _tmain(int argc, _TCHAR* argv[])

{

double x_new, x_old, y_new, y_old;

double e = 0.01;

x_new = 1.2;

y_new = 0.5;

do

{

x_old = x_new;

y_old = y_new;

x_new = x_old + (dFdY(x_old, y_old)*F(x_old, y_old) - dGdY(x_old, y_old)*G(x_old, y_old)) / (dGdY(x_old, y_old)*dFdX(x_old, y_old) - dFdY(x_old, y_old)*dGdX(x_old, y_old));

y_new = y_old + (dGdX(x_old, y_old)*F(x_old, y_old) - dFdX(x_old, y_old)*G(x_old, y_old)) / (dGdY(x_old, y_old)*dFdX(x_old, y_old) - dFdY(x_old, y_old)*dGdX(x_old, y_old));

}

while((abs(x_new - x_old) >= e) && (abs(x_new - x_old) >= e));

cout<<"x = "<<x_new<<endl;

cout<<"y = "<<y_new<<endl;

getch();

}

    1. Результат программы (метода Ньютона)

  1. Метод простой итерации

Напомним, что нам требуется решить систему линейных уравнений, которая в матричном виде записывается как:

,

где .

Предположим, что диагональные элементы матриц A исходной системы не равны 0 (aii ≠ 0, i = 1, 2, …, n). Разрешим первое уравнение системы относительно x1, второе относительно x2 и т.д. Получим следующую эквивалентную систему, записанную в скалярном виде:

 (1),

Теперь, задав нулевое приближение , по рекуррентным соотношениям (1) можем выполнять итерационный процесс, а именно:

 (2)

Аналогично находятся следующие приближения , где в (2) вместо  необходимо подставить .

Или в общем случае:

. (3)

или 

Условие окончания итерационного процесса .

Достаточное условие сходимости: Если выполнено условие диагонального преобладания, т.е. , то итерационный процесс (3) сходится при любом выборе начального приближения. Если исходная система уравнений не удовлетворяет условию сходимости, то ее приводят к виду с диагональным преобладанием.

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

Замечание. Указанное выше условие сходимости является достаточным, т.е. если оно выполняется, то процесс сходится. Однако процесс может сходиться и при отсутствии диагонального преобладания, а может и не сойтись.

Пример.

Решить систему линейных уравнений с точностью :

 

8

4

2

 

10

 

x1

 

=

3

5

1

=

5

=

x2

 

 

3

–2

10

 

4

 

x3

 

Решение прямыми методами, например, обратной матрицей, даёт решение:

.

Найдем решение методом простой итерации. Проверяем условие диагонального преобладания: .

Приводим систему уравнений к виду (1):

Начальное приближение . Дальнейшие вычисления оформим в виде таблицы:

k

x1

x2

x3

точность

0

0

0

0

 

1

1.250

1.000

0.400

1.2500

2

0.650

0.170

0.225

0.8300

3

1.109

0.565

0.239

0.4588

………

4

0.908

0.287

0.180

0.2781

5

1.061

0.419

0.185

0.1537

6

0.994

0.326

0.165

0.0931

7

1.046

0.370

0.167

0.0515

8

1.023

0.594

0.160

0.2235

9

0.913

0.582

0.212

0.1101

10

0.906

0.505

0.242

0.0764

11

0.937

0.495

0.229

0.0305

12

0.945

0.516

0.218

0.0210

……

13

0.937

0.523

0.220

0.0077

Здесь  

 

  1. Метод Зейделя (Гаусса-Зейделя)

Расчетные формулы имеют вид:

т.е. для подсчета i–й компоненты (k+1)–го приближения к искомому вектору используется уже вычисленное на этом, т.е. (k+1)–м шаге, новые значения первых i–1 компонент.

Подробные формулы имеют вид:

Достаточное условие сходимости этого метода такое же, как и для метода простой итерации, т.е. диагональное преобладание:

Начальное приближение:

Найдем решение примера системы уравнений методом Гаусса – Зейделя.

Расчетные формулы:

k

x1

x2

x3

точность

0

0

0

0

 

1

1.250

0.250

0.075

1.2500

2

1.106

0.321

0.132

0.1438

3

1.056

0.340

0.151

0.0500

4

1.042

0.344

0.156

0.0139

5

1.039

0.346

0.157

0.0036

Так как, что метод Гаусса-Зейделя является модифицированным методом простых итераций, реализуем оба метода в одной программе.

Точность eps = 0.0001

    1. Листинг программы (Методы простой итерации и Гаусса-Зейделя):

#include <stdafx.h>

#include <math.h>

#include <iostream>

#include <conio.h>

#include <locale>

using namespace std;

double funcx(double, double);

double funcy(double, double);

int _tmain(int argc, _TCHAR* argv[])

{

setlocale(LC_ALL,"Russian");

cout<<"Метод простых итераций\n"<<endl;

int k = 0;

double x, y, newx, tx, ty, newy, eps;

x=1.23;

y=0.55;

eps=0.0001;

do

{

k++;

tx = x;

ty = y;

newx = funcx(x, y);

newy = funcy(x, y);

x = newx;

y = newy;

cout<<"Итерация #"<<k<<endl<<"x = "<<x<<", y = "<<y<<endl;

}

while(fabs(x - tx) > eps || fabs(y - ty) > eps);

cout<<"Ответ:"<<endl<<"x = "<<newx<<", y = "<<newy<<endl;

cout<<"\n"<<endl;

cout<<"Метод Гаусса-Зейделя"<<endl;

k=0;

x=1.23;

y=0.55;

eps = 0.0001;

do

{

k++;

tx = x;

ty = y;

newx = funcx(x, y);

x = newx;

newy = funcy(x, y);

y = newy;

cout<<"Итерация #"<<k<<endl<<"x = "<<x<<", y = "<<y<<endl;

}

while(fabs(x - tx) > eps && fabs(y - ty) > eps);

cout<<"Ответ:"<<endl<<"x = "<<newx<<", y = "<<newy<<endl;

getch();

}

double funcx(double x, double y)

{

return (atan(x*x)-0.3)/y;

}

double funcy(double x, double y)

{

return sqrt(fabs(1-0.45*x*x));

}

    1. Результат программы (метод Гаусса-Зейделя):

  1. Вывод:

Метод Зейделя работает быстрее, чем метод простых итераций.

9

Соседние файлы в папке docx54