
ПР №3 Разработка алгоритмов и программ, решающих линейные уравнения
.docФЕДЕРАЛЬНОЕ АГЕНТСТВО СВЯЗИ
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М.А. БОНЧ-БРУЕВИЧА»
(СПбГУТ)
Кафедра безопасности информационных систем
ОТЧЁТ
по итоговой работе №3 на тему: «Разработка алгоритмов и программ, решающих линейные уравнения»
по дисциплине «Алгоритмы и структуры данных»
Выполнил: студент группы ИСТ-931, Гетманченко П.А.
«13» октября 2020 г. ___________/П.А. Гетманченко /
Принял: к.ф.-м.н., доцент, Моисеев И. А.
«13» октября 2020 г. __________/ И. А. Моисеев /
Основная часть
Цель работы: разработать пользовательский алгоритм и программу для решения линейных уравнений двумя разными методами, такими как: метод Крамера и метод Гаусса. Приобрести навыки и умения анализа алгоритма.
Результаты выполнения работы
Задание 1:
Решить линейное уравнение через определители (метод Крамера).
Пример из книги:
#include <iostream>
#include <iomanip>
#include <Windows.h>
using namespace std;
// вычисление определителя матрицы
double Determ(double** A, int size, int &opCount1, int& opCount2)
{
double** matr = nullptr;
double det = 0;
int i, j;
switch (size)
{
case 1:
det = A[0][0];
break;
case 2:
det = A[0][0] * A[1][1] - A[0][1] * A[1][0];
// 2 умножения и одно вычитание
opCount1 += 2;
opCount2++;
break;
default:
matr = new double*[size - 1];
for (i = 0; i < size; ++i)
{
for (j = 0; j < size - 1; ++j)
{
if (j < i)
matr[j] = A[j];
else
matr[j] = A[j + 1];
}
det += pow((double)-1, (i + j)) * Determ(matr, size - 1, opCount1, opCount2) * A[i][size - 1];
// если считать число операций как по формуле
// здесь есть 2 операции:
// 1) умножение определителя минора на элемент матрицы
// 2) прибавляем (или вычистаем) получившееся значение к текущему значению определителя
opCount1++;
opCount2++;
}
delete[] matr;
break;
}
return det;
}
// решение СЛАУ через определитель (метод Крамера)
void Kramer(double** A, double* x, int size)
{
int opCount1 = 0; // счётчик операций (умножение и деление)
int opCount2 = 0; // счётчик операций (сложение и вычитание)
// вычисляем определитель матрицы системы
double det = Determ(A, size, opCount1, opCount2);
// выделяем память под матрицу
// для вычисления дополнительных определителей
double** B = new double*[size];
for (int i = 0; i < size; i++)
B[i] = new double[size];
for (int k = 0; k < size; k++)
{
// заполняем матрицу B
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (j == k)
B[i][j] = A[i][size];
else
B[i][j] = A[i][j];
}
}
// вычисляем значение k-го корня
x[k] = Determ(B, size, opCount1, opCount2) / det;
opCount1++; // ещё одна операция деления
}
// освобождаем память
for (int i = 0; i < size; i++)
delete[] B[i];
delete[] B;
cout << "Вычисление через определитель (метод Крамера) завершено" << endl
<< "выполнено " << opCount1 + opCount2 << " арифметических операций, их них:" << endl;
cout << "операций умножения и деления - " << opCount1 << endl;
cout << "операций сложения и вычитания - " << opCount2 << endl;
}
int main()
{
setlocale(LC_ALL, "Russian");
// матрица СЛАУ
double src[][5] = {
{ 2, 1, -5, 1, 8},
{ 1, -3, 0, -6, 9},
{ 0, 2, -1, 2, -5},
{ 1, 4, -7, 6, 0}
};
// создаём и заполняем динамический массив указателей на строки
// для работы с матрицей системы
const int size = sizeof(src) / sizeof(src[0]);
double** rows = new double*[size];
for (size_t i = 0; i < size; i++)
rows[i] = src[i];
//int size = 0;
//cout << "Введите размерность СЛАУ: ";
//cin >> size;
//// выделяем память под матрицу системы
//double ** rows = new double* [size];
//for (int i = 0; i < size; i++)
// rows[i] = new double[size + 1];
//cout << "Введите построчно элементы матрицы СЛАУ" << endl;
//for (int i = 0; i < size; i++)
//{
// for (int j = 0; j <= size; j++)
// {
// //cout << "A[" << i + 1 << "][" << j + 1 << "] = ";
// cin >> rows[i][j];
// }
//}
cout << "Система заполнена" << endl;
for (int i = 0; i < size; i++)
{
for (int j = 0; j <= size; j++)
cout << setw(4) << rows[i][j];
cout << endl;
}
cout << endl;
// массив для корней системы
double *x = new double[size];
// переменные для вычисления времени выполнения
__int64 timerFreq, counterAtStart, counterAtStop;
double duration;
// засекаем время начала вычислений
QueryPerformanceFrequency((LARGE_INTEGER*)&timerFreq);
QueryPerformanceCounter((LARGE_INTEGER*)&counterAtStart);
// решаем систему методом Крамера (определителей)
Kramer(rows, x, size);
QueryPerformanceCounter((LARGE_INTEGER*)&counterAtStop);
duration = (double)(counterAtStop - counterAtStart) / timerFreq;
cout << "Время выполнения: " << duration << " мс" << endl;
// выводим резулльтат на экран
cout << endl << "Решение СЛАУ" << endl;
for (int i = 0; i < size; i++)
cout << "x[" << i + 1 << "] = " << x[i] << endl;
// освобождаем память
//for (size_t i = 0; i < size; i++)
// delete[] rows[i];
delete[] rows;
delete[] x;
system("Pause");
return 0;
}
Результат:
Сама программа решения линейного уравнения через определители (метод Крамера):
#include <iostream>
#include <iomanip>
#include <Windows.h>
using namespace std;
// вычисление определителя матрицы
double Determ(double** A, int size, int &opCount1, int& opCount2)
{
double** matr = nullptr;
double det = 0;
int i, j;
switch (size)
{
case 1:
det = A[0][0];
break;
case 2:
det = A[0][0] * A[1][1] - A[0][1] * A[1][0];
// 2 умножения и одно вычитание
opCount1 += 2;
opCount2++;
break;
default:
matr = new double*[size - 1];
for (i = 0; i < size; ++i)
{
for (j = 0; j < size - 1; ++j)
{
if (j < i)
matr[j] = A[j];
else
matr[j] = A[j + 1];
}
det += pow((double)-1, (i + j)) * Determ(matr, size - 1, opCount1, opCount2) * A[i][size - 1];
// если считать число операций как по формуле
// здесь есть 2 операции:
// 1) умножение определителя минора на элемент матрицы
// 2) прибавляем (или вычистаем) получившееся значение к текущему значению определителя
opCount1++;
opCount2++;
}
delete[] matr;
break;
}
return det;
}
// решение СЛАУ через определитель (метод Крамера)
void Kramer(double** A, double* x, int size)
{
int opCount1 = 0; // счётчик операций (умножение и деление)
int opCount2 = 0; // счётчик операций (сложение и вычитание)
// вычисляем определитель матрицы системы
double det = Determ(A, size, opCount1, opCount2);
// выделяем память под матрицу
// для вычисления дополнительных определителей
double** B = new double*[size];
for (int i = 0; i < size; i++)
B[i] = new double[size];
for (int k = 0; k < size; k++)
{
// заполняем матрицу B
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (j == k)
B[i][j] = A[i][size];
else
B[i][j] = A[i][j];
}
}
// вычисляем значение k-го корня
x[k] = Determ(B, size, opCount1, opCount2) / det;
opCount1++; // ещё одна операция деления
}
// освобождаем память
for (int i = 0; i < size; i++)
delete[] B[i];
delete[] B;
cout << "Вычисление через определитель (метод Крамера) завершено" << endl
<< "выполнено " << opCount1 + opCount2 << " арифметических операций, их них:" << endl;
cout << "операций умножения и деления - " << opCount1 << endl;
cout << "операций сложения и вычитания - " << opCount2 << endl;
}
int main()
{
setlocale(LC_ALL, "Russian");
//// матрица СЛАУ
//double src[][5] = {
// { 2, 1, -5, 1, 8},
// { 1, -3, 0, -6, 9},
// { 0, 2, -1, 2, -5},
// { 1, 4, -7, 6, 0}
//};
//// создаём и заполняем динамический массив указателей на строки
//// для работы с матрицей системы
//const int size = sizeof(src) / sizeof(src[0]);
//double** rows = new double* [size];
//for (size_t i = 0; i < size; i++)
// rows[i] = src[i];
int size = 0;
cout << "Введите размерность СЛАУ: ";
cin >> size;
// выделяем память под матрицу системы
double ** rows = new double*[size];
for (int i = 0; i < size; i++)
rows[i] = new double[size + 1];
cout << "Введите построчно элементы матрицы СЛАУ" << endl;
for (int i = 0; i < size; i++)
{
for (int j = 0; j <= size; j++)
{
//cout << "A[" << i + 1 << "][" << j + 1 << "] = ";
cin >> rows[i][j];
}
}
//cout << "Введите элементы столбца b в правой части СЛАУ" << endl;
//for (int i = 0; i < size; i++)
//{
// cout << "b[" << i + 1 << "] = ";
// cin >> rows[i][size];
//}
cout << "Система заполнена" << endl;
for (int i = 0; i < size; i++)
{
for (int j = 0; j <= size; j++)
cout << setw(4) << rows[i][j];
cout << endl;
}
cout << endl;
// массив для корней системы
double *x = new double[size];
// переменные для вычисления времени выполнения
__int64 timerFreq, counterAtStart, counterAtStop;
double duration;
// засекаем время начала вычислений
QueryPerformanceFrequency((LARGE_INTEGER*)&timerFreq);
QueryPerformanceCounter((LARGE_INTEGER*)&counterAtStart);
// решаем систему методом Крамера (определителей)
Kramer(rows, x, size);
QueryPerformanceCounter((LARGE_INTEGER*)&counterAtStop);
duration = (double)(counterAtStop - counterAtStart) / timerFreq;
cout << "Время выполнения: " << duration << " мс" << endl;
// выводим резулльтат на экран
cout << endl << "Решение СЛАУ" << endl;
for (int i = 0; i < size; i++)
cout << "x[" << i + 1 << "] = " << x[i] << endl;
// освобождаем память
for (size_t i = 0; i < size; i++)
delete[] rows[i];
delete[] rows;
delete[] x;
system("Pause");
return 0;
}
Результат:
Задание 2:
Решить линейное уравнение методом Гаусса.
Пример из книги:
#include <iostream>
#include <iomanip>
#include <Windows.h>
using namespace std;
// решение СЛАУ методом Гаусса
void Gauss(double** A, double* x, int size)
{
double tmp;
int opCount1 = 0; // счётчик операций (умножение и деление)
int opCount2 = 0; // счётчик операций (сложение и вычитание)
// прямой проход
for (int i = 0; i < size; i++)
{
tmp = A[i][i];
for (int j = i; j <= size; j++)
{
A[i][j] /= tmp;
opCount1++;
}
for (int k = i + 1; k < size; k++)
{
tmp = A[k][i];
for (int j = i; j <= size; j++)
{
A[k][j] -= tmp * A[i][j];
opCount1++;
opCount2++;
}
}
}
// обратный проход
for (int i = size - 1; i >= 0; i--)
{
tmp = A[i][size];
for (int j = i + 1; j < size; j++)
{
tmp -= A[i][j] * x[j];
opCount1++;
opCount2++;
}
x[i] = tmp / A[i][i];
opCount1++;
}
cout << "Вычисление методом Гаусса завершено" << endl
<< "выполнено " << opCount1 + opCount2 << " арифметических операций, их них:" << endl;
cout << "операций умножения и деления - " << opCount1 << endl;
cout << "операций сложения и вычитания - " << opCount2 << endl;
}
int main()
{
setlocale(LC_ALL, "Russian");
// матрица СЛАУ
double src[][5] = {
{ 2, 1, -5, 1, 8},
{ 1, -3, 0, -6, 9},
{ 0, 2, -1, 2, -5},
{ 1, 4, -7, 6, 0}
};
// создаём и заполняем динамический массив указателей на строки
// для работы с матрицей системы
const int size = sizeof(src) / sizeof(src[0]);
double** rows = new double*[size];
for (size_t i = 0; i < size; i++)
rows[i] = src[i];
//int size = 0;
//cout << "Введите размерность СЛАУ: ";
//cin >> size;
//// выделяем память под матрицу системы
//double** rows = new double* [size];
//for (int i = 0; i < size; i++)
// rows[i] = new double[size + 1];
//cout << "Введите построчно элементы матрицы СЛАУ" << endl;
//for (int i = 0; i < size; i++)
//{
// for (int j = 0; j <= size; j++)
// {
// //cout << "A[" << i + 1 << "][" << j + 1 << "] = ";
// cin >> rows[i][j];
// }
//}
cout << "Система заполнена" << endl;
for (int i = 0; i < size; i++)
{
for (int j = 0; j <= size; j++)
cout << setw(4) << rows[i][j];
cout << endl;
}
cout << endl;
// массив для корней системы
double* x = new double[size];
// переменные для вычисления времени выполнения
__int64 timerFreq, counterAtStart, counterAtStop;
double duration;
// засекаем время начала вычислений
QueryPerformanceFrequency((LARGE_INTEGER*)&timerFreq);
QueryPerformanceCounter((LARGE_INTEGER*)&counterAtStart);
// решаем систему методом Гаусса
Gauss(rows, x, size);
QueryPerformanceCounter((LARGE_INTEGER*)&counterAtStop);
duration = (double)(counterAtStop - counterAtStart) / timerFreq;
cout << "Время выполнения: " << duration << " мс" << endl;
// выводим резулльтат на экран
cout << endl << "Решение СЛАУ" << endl;
for (int i = 0; i < size; i++)
cout << "x[" << i + 1 << "] = " << x[i] << endl;
// освобождаем память
//for (size_t i = 0; i < size; i++)
// delete[] rows[i];
delete[] rows;
delete[] x;
system("Pause");
return 0;
}
Результат:
Сама программа решения линейного уравнения методом Гаусса:
#include <iostream>
#include <iomanip>
#include <Windows.h>
using namespace std;
// решение СЛАУ методом Гаусса
void Gauss(double** A, double* x, int size)
{
double tmp;
int opCount1 = 0; // счётчик операций (умножение и деление)
int opCount2 = 0; // счётчик операций (сложение и вычитание)
// прямой проход
for (int i = 0; i < size; i++)
{
tmp = A[i][i];
for (int j = i; j <= size; j++)
{
A[i][j] /= tmp;
opCount1 ++;
}
for (int k = i + 1; k < size; k++)
{
tmp = A[k][i];
for (int j = i; j <= size; j++)
{
A[k][j] -= tmp * A[i][j];
opCount1 ++;
opCount2 ++;
}
}
}
// обратный проход
for (int i = size - 1; i >= 0; i--)
{
tmp = A[i][size];
for (int j = i + 1; j < size; j++)
{
tmp -= A[i][j] * x[j];
opCount1++;
opCount2++;
}
x[i] = tmp / A[i][i];
opCount1++;
}
cout << "Вычисление методом Гаусса завершено" << endl
<< "выполнено " << opCount1 + opCount2 << " арифметических операций, их них:" << endl;
cout << "операций умножения и деления - " << opCount1 << endl;
cout << "операций сложения и вычитания - " << opCount2 << endl;
}
int main()
{
setlocale(LC_ALL, "Russian");
//// матрица СЛАУ
//double src[][5] = {
// { 2, 1, -5, 1, 8},
// { 1, -3, 0, -6, 9},
// { 0, 2, -1, 2, -5},
// { 1, 4, -7, 6, 0}
//};
//// создаём и заполняем динамический массив указателей на строки
//// для работы с матрицей системы
//const int size = sizeof(src) / sizeof(src[0]);
//double** rows = new double* [size];
//for (size_t i = 0; i < size; i++)
// rows[i] = src[i];
int size = 0;
cout << "Введите размерность СЛАУ: ";
cin >> size;
// выделяем память под матрицу системы
double** rows = new double* [size];
for (int i = 0; i < size; i++)
rows[i] = new double[size + 1];
cout << "Введите построчно элементы матрицы СЛАУ" << endl;
for (int i = 0; i < size; i++)
{
for (int j = 0; j <= size; j++)
{
//cout << "A[" << i + 1 << "][" << j + 1 << "] = ";
cin >> rows[i][j];
}
}
//cout << "Введите элементы столбца b в правой части СЛАУ" << endl;
//for (int i = 0; i < size; i++)
//{
// cout << "b[" << i + 1 << "] = ";
// cin >> rows[i][size];
//}
cout << "Система заполнена" << endl;
for (int i = 0; i < size; i++)
{
for (int j = 0; j <= size; j++)
cout << setw(4) << rows[i][j];
cout << endl;
}
cout << endl;
// массив для корней системы
double* x = new double[size];
// переменные для вычисления времени выполнения
__int64 timerFreq, counterAtStart, counterAtStop;
double duration;
// засекаем время начала вычислений
QueryPerformanceFrequency((LARGE_INTEGER*)&timerFreq);
QueryPerformanceCounter((LARGE_INTEGER*)&counterAtStart);
// решаем систему методом Гаусса
Gauss(rows, x, size);
QueryPerformanceCounter((LARGE_INTEGER*)&counterAtStop);
duration = (double)(counterAtStop - counterAtStart) / timerFreq;
cout << "Время выполнения: " << duration << " мс" << endl;
// выводим резулльтат на экран
cout << endl << "Решение СЛАУ" << endl;
for (int i = 0; i < size; i++)
cout << "x[" << i + 1 << "] = " << x[i] << endl;
// освобождаем память
for (size_t i = 0; i < size; i++)
delete[] rows[i];
delete[] rows;
delete[] x;
system("Pause");
return 0;
}
Результат:
Выводы: были разработаны пользовательские алгоритмы и программы для решения линейных уравнений двумя разными методами, такими как: метод Крамера и метод Гаусса. Также были приобретены навыки и умения анализа алгоритма. Во всех программах при одной и той же матрице ответ совпадает: х1=3, х2=-4, х3=-1, х4=1.
Содержание
Основная часть 2
Результаты выполнения работы 2
Выводы 14
Содержание 14
САНКТ-ПЕТЕРБУРГ 2020