Для написания программы, решающей систему линейных уравнения методом итерации или Зейделя, Вам потребуется среда разработки, например Visual Studio 2008 или Dev-C++.
Создадим новый проект пустой проект и добавим в него файл исходного кода — main.cpp со следующим содержимым
Листинг 1.1 — main.cpp
#include <iostream>
#include <cmath>
#include "norm.h"
#include "iterat.h"
using namespace std;
int main()
{
setlocale(LC_ALL, "");
double eps, A[10][10], B[10];
int N, i, j;
int method;
cout << "Введите размер квадратной матрицы: ";
cin >> N;
cout << "Введите точность вычислений: ";
cin >> eps;
cout << "Заполните матрицу А: " << endl << endl;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
cout << "A[" << i << "][" << j << "] = ";
cin >> A[i][j];
}
}
cout << "\nВаша матрица А:" << endl;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
cout << A[i][j] << " ";
}
cout << endl;
}
cout << "\nЗаполните столбец свободных членов: " << endl;
for (i = 0; i < N; i++) {
cout << "В[" << i+1 << "] = ";
cin >> B [i];
}
cout << "\nВыберите метод решения системы (1 - Гаусс / 2 - Зейдель): ";
cin >> method;
cout << endl;
iterat(A,B,N,eps,method);
return 0;
}
Теперь создадим заголовочный файл norm.h, содержащий прототипы функций,
вычисляющих нормы матрицы, и iterat.h, содержащий прототип функции
iterat()
, которая считает количество итераций.
Листинг 1.2 — norm.h
double firstNorm(double [10][10], int n, int m);
double secondNorm(double [10][10], int n, int m);
double thirdNorm(double [10][10], int n, int m);
Листинг 1.3 — iterat.h
double iterat(double A[10][10], double B[10], int N, double eps, int method);
Теперь добавим в проект третий заголовочный файл okr.h — в нем будет находиться прототип функции округления
Листинг 1.4 — okr.h
double okr(double X, double eps);
Создадим еще три файла — norm.cpp, iterat.cpp и okr.cpp
Листинг 1.5 — norm.cpp
#include <cmath>
double firstNorm(double A[10][10], int n, int m)
{
int i, j;
double sum = 0, subSum;
for (i = 0; i < n; i++) {
subSum = 0;
for (j = 0; j < m; j++) {
subSum += abs(A[i][j]);
}
if(subSum > sum) {
sum = subSum;
}
}
return sum;
}
double secondNorm(double A[10][10], int n, int m)
{
int i, j;
double sum = 0, subSum;
for (j = 0; j < n; j++) {
subSum = 0;
for (i = 0; i < m; i++) {
subSum += abs(A[i][j]);
}
if(subSum > sum) {
sum = subSum;
}
}
return sum;
}
double thirdNorm(double A[10][10], int n, int m)
{
int i, j;
double sum = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
sum += (A[i][j] * A[i][j]);
}
}
sum = sqrt(sum);
return sum;
}
В файле iterat.cpp будет описана функция, вычисляющая количество итераций по по методу Зейделя, либо по методу простых итераций.
Листинг 1.6 — iterat.cpp
#include <iostream>
#include <cmath>
#include "norm.h"
#include "okr.h"
using namespace std;
double iterat(double A[10][10], double B[10], int N, double eps, int method)
{
if (thirdNorm(A, N, N) < 1) {
int k = 0;
int i, j;
double X[10];
double Y[10];
double s;
double g;
for(i = 0; i < N; i++) {
X[i] = B[i];
}
do {
s = 0; k++;
if (method != 1 && method != 2) {
while (method != 1 && method != 2) {
cerr << "Неверное значение!" << endl;
cout << "\nВыберите метод решения системы (1 - Гаусс / 2 - Зейдель): ";
cin >> method;
cout << endl;
}
}
if (method == 1) { // Решаем систему методом Гаусса.
for (i = 0; i < N; i++) {
Y[i] = B[i];
for (j = 0; j < N; j++) {
Y[i] = Y[i] + A[i][j] * X[j];
}
s += (X[i] - Y[i]) * (X[i] - Y[i]);
}
for (i = 0; i < N; i++) {
X[i] = Y[i];
}
} else if (method == 2) { // Решаем систему методом Зейделя.
for (i = 0; i < N; i++) {
g = B[i];
for (j = 0; j < N; j++) {
g = g + A[i][j] * X[j];
}
s += (X[i] - g) * (X[i] - g);
X[i] = g;
}
}
} while (sqrt(s) >= eps * (1 - thirdNorm(A, N, N)) / thirdNorm(A, N, N));
if (method == 1 || method == 2) {
cout << "Решение системы:" << endl;
for (i = 0; i < N; i++) {
cout << "X" << i << " = " << okr(X[i],eps) << endl;
}
cout << "Число итераций: " << k-1 << endl;
cout << "Первая норма матрицы A: " << firstNorm(A,N,N) << endl;
cout << "Вторая норма матрицы A: " << secondNorm(A,N,N) << endl;
cout << "Третья норма матрицы A: " << thirdNorm(A,N,N) << endl;
}
} else {
cerr << "Условие сходимости по евклидовой метрике не выполняется!" << endl;
}
return 0;
}
И последний файл — okr.cpp, содержащий определение функции округления
Листинг 1.7 — okr.cpp
#include <cmath>
using namespace std;
double okr(double X, double eps)
{
int i = 0;
while (eps != 1) {
i++;
eps *= 10;
}
int okr = pow(double(10), i);
X = int(X * okr + 0.5) / double(okr);
return X;
}
Вы можете скачать полный архив со всем файлами проекта.
Комментарии к статье: 3
Возможность комментировать эту статью отключена автором. Возможно, во всем виновата её провокационная тематика или большое обилие флейма от предыдущих комментаторов.
Если у вас есть вопросы по содержанию статьи, рекомендуем вам обратиться за помощью на наш форум.