Вы находитесь на странице: 1из 26

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ

ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ


УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ
«МАГНИТОГОРСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
ИМ. Г. И. НОСОВА»
(ФГБОУ ВО «МГТУ ИМ. Г.И. НОСОВА»)

Кафедра вычислительной техники и программирования

КУРСОВАЯ РАБОТА

по дисциплине «Структуры и модели данных»

на тему: «Создание библиотеки контейнерных классов для реализации


структуры данных «Матрица»»

Исполнитель: Медведев И.Д. студент 2 курса, группа АВб-20-12

Руководитель: Торчинский В.Е., старший преподаватель кафедры ВИиП

Работа допущена к защите «____» __________2022 г. _____________

Работа защищена «____» ___________ 2022 г. с оценкой ___________ ___________

Магнитогорск, 2022
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ
УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ
«МАГНИТОГОРСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
ИМ. Г.И. НОСОВА»
(ФГБОУ ВО «МГТУ ИМ. Г.И. НОСОВА»)

Кафедра вычислительной техники и программирования

ЗАДАНИЕ НА КУРСОВУЮ РАБОТУ

Тема: Создание библиотеки контейнерных классов для реализации структуры


данных «Матрица»

Обучающемуся Медведеву Игорю Дмитриевичу

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


реализации структуры данных «Матрица» на основе статических и динамических
структур данных

Срок сдачи: «_____» __________ 2022 г.

Руководитель: _________________ /В.Е. Торчинский /

Задание получил: _________________ /И.Д. Медведев /

2
Введение

Матрица – прямоугольная таблица, заполненная числами. Размер


задается количеством строк и столбцов. Они естественным образом
возникают при решении систем линейных уравнений, а также при
рассмотрении линейных преобразований. Решение системы линейных
уравнений требуется во многих сферах деятельности: физика, химия,
информатика, экономика. Также матрицы очень часто используются при
разработке моделей. Благодаря матрицам можно обрабатывать цифровые
изображения, разрабатывать игровые движки.
Целью данной курсовой работы является:
1) Изучение истории матриц;
2) Изучение функций с матрицами;
3) Изучение операций с матрицами;
4) Создание библиотеки контейнерных классов для реализации
структуры данных «Матрица» и различных операций с ней.
Теоретическая задача курсовой работы заключена в том, чтобы
проанализировать и изучить данные о различных операциях с матрицами.
Практическая задача курсовой работы заключена в том, чтобы
разработать библиотеку на языке C++, а точнее программный код
содержащий математическую сущность нашей структуры данных, которая
будет служить для её реализации.

3
Содержание

Введение
1. Теоретическое обоснование шаблонного класса «Матрица»
1.1. История матриц
1.2. Функции и операции с матрицами
2. Практическая реализация шаблонного класса «Матрица»
2.1. Описание работы программы
2.2. Пример работы программы
Заключение
Список литературы
Приложение

4
1.Теоретическое обоснование шаблонного класса «Матрица»

1.1. История матриц.

Первые упоминания матриц нашли в древнем Китае, они носили


названия «волшебный квадрат». В основном матрицы использовались для
решения линейных уравнений[1]. Чуть позже с ними начали работать арабские
математики, примерно в это же время и появился принцип сложения матриц.
После развития теории определителей в конце 17-го века Габриэль Крамер
начал разрабатывать свою теорию в 18-м столетии и опубликовал «правило
Крамера» в 1751 году. Примерно в этом же промежутке времени появился
«метод Гаусса». Теория матриц начала своё существование в середине XIX
века в работах Уильяма Гамильтона и Артура Кэли. Фундаментальные
результаты в теории матриц принадлежат Вейерштрассу, Жордану,
Фробениусу. Термин «матрица» ввел Д. Сильвестр в 1850 г[2].

1.2. Функции и операции с матрицами.


Для матрицы определены следующие алгебраические операции:

1) Сложение матриц, имеющих один и тот же размер;


2) Умножение матриц подходящего размера (матрицу, имеющую n
столбцов, можно умножить справа на матрицу, имеющую n строк);
3) Умножение матрицы на скаляр.

Эти операции являются основой матричного представления линейных


операторов и линейных преобразований координат, все остальные операции
(деление на число или разность матриц) выводятся из этих трех.

Существуют и другие, более сложные операции:

1) Транспонирование. Если матрица A = (ai,j), то AT = (aj,i).


2) Минор. В линейной алгебре – определитель некоторой меньшей
квадратной матрицы B, вырезанной из матрицы A, путем удаления
одной или нескольких ее строк и столбцов.

5
3) Алгебраическое дополнение. Если минор матрицы по i-ой строке и j-го
столбца обозначить за Mij, тогда алгебраическим дополнением будет
число Aij = (-1)i+jMij
4) Определитель. Сумма элементов строки (столбца), каждый из которых
умножается на его соответствующее алгебраическое дополнение.
5) Обратная матрица. Это транспонированная матрица из алгебраических
дополнений разделенная на определитель.

6
2.Практическая реализация структуры данных «Матрица».

2.1. Описание работы программы

template <class T> class Matrix {


private:
T** matrix;
size_t rows, cols;

void clear();
T*& operator[](size_t);
public:
Matrix(size_t, size_t, const T& = T());
Matrix(const Matrix&);
~Matrix();

size_t getRows() { return rows; }


size_t getCols() { return cols; }

T& operator()(size_t, size_t);

Matrix operator*(const T);


Matrix operator/(const T);
Matrix operator*(const Matrix&);
Matrix operator+(const Matrix&);
Matrix operator-(const Matrix&);
Matrix operator*=(const T);
Matrix operator/=(const T);
Matrix operator*=(const Matrix&);
Matrix operator+=(const Matrix&);
Matrix operator-=(const Matrix&);
Matrix operator=(const Matrix&);

Matrix transposition();

double determinant();
double determinantAlgebraic();
double determinantGauss();

double minor(size_t, size_t);


double algebraicComplement(size_t, size_t);
Matrix<double> inverse();
};

7
Созданный контейнерный класс имеет три поля: два беззнаковых
числа и двойной указатель типа Т, соответственно, размеры матрицы и
двумерный массив, в котором хранятся её элементы. В классе реализованы
два конструктора. В первом один параметр по умолчанию (им заполняются
все ячейки матрицы) и два беззнаковых числа – размеры матрицы, в данном
конструкторе создается двумерный динамический массив. Второй –
конструктор копирования. Прописан и деструктор, который очищает
созданный двумерный динамический массив.

Обращение к элементам происходит через оператор (), который


принимает два беззнаковых числа – строку и столбец и возвращает ссылку
соответствующего элемента матрицы.

Были перегружены следующие операторы:

 «*», который математически умножает матрицу на число или на


другую матрицу.
 «/» – обратное действие к умножению матрицы на число.
 «+», который математически складывает матрицы.
 «-» – обратное действие к сумме матриц.
 «=» и другие операторы присваивания, совмещенные с
вышеперечисленными операциями.

Методы getRows() и getCols() возвращают соответственно количество


строк и столбцов матрицы.

Метод transposition() возвращает транспонированную матрицу.

Было реализовано два метода расчета определителя, каждый из


которых имеет свои преимущества и недостатки.

 Расчет определителя через алгебраическое дополнение. Минусом этого


метода является сложность по времени, которая растет по экспоненте,

8
если размер квадратной разницы больше 2. Плюсом является его
точность, поскольку потерь при делении чисел не возникает.
 Расчет определителя методом Гаусса. По результатам тестов, данный
метод работает намного быстрее предыдущего, однако, точность
начинает падать при размерах матрицы выше 10. Его сложность
равняется О(n3).

Был реализован общий метод вычисления определителя, который, в


зависимости от размерности матрицы вызывает один из двух
вышеперечисленных методов (что не запрещает пользоваться публичными
методами расчета определителя). Данный метод в первую очередь должен
быть точным, и лишь во вторую быстрым. Поэтому для матрицы
размерности от 3 до 9 включительно вызывается метод Гаусса, а во всех
остальных случаях метод алгебраического дополнения.

Для проведения тестов было реализовано 2 класса: TestMatrix и Timer.


В первом классе написано несколько методов для проверки
работоспособности класса Matrix, второй создан для замера времени работы
выбранного куска кода.

Метод для сравнения точности алгоритма Гаусса принимает в


качестве параметра размер матрицы и количество проверок. Логика работы
данного метода следующая: создается матрица определенного размера,
рассчитывается определитель через алгебраическое дополнение и метод
Гаусса, потом идет сравнение двух полученных величин, допускаемая
погрешность: ε = 10-7. Если разница двух величин больше чем ε, то данный
метод возвращает false. И так определенное количество итераций. Если цикл
завершается не раньше положенного, то данный метод возвращает true.

Метод для сравнения времени работы принимает в качестве параметра


размер матрицы и количество проверок, а возвращает массив из двух

9
элементов – время расчета определителя методом алгебраического
дополнения и методом Гаусса соответственно определенное количество раз.

Самый главный метод – расчет обратной матрицы. Для него было


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

2.2. Пример работы программы


В качестве первого примера создадим матрицу и выведем обратную к
ней. Исходные значения можно посмотреть на рисунке ниже. При её расчете
будут задействованы все методы класса: умножения матриц, транспозиции,
деления матрицы на число, поиска минора и алгебраического дополнения и
т.д.

Рисунок 1 – Входные данные для расчета обратной матрицы

Выходные данные представлены ниже.

Рисунок 2 – Выходные данные расчета обратной матрицы.

Если самостоятельно правильно посчитать обратную матрицу


получится такой же результат.

10
В качестве второго примера выведем время расчета определителя
1000 раз матрицы 8х8 для каждого алгоритма в миллисекундах. Ниже
представлены выходные данные.

Рисунок 3 – Выходные данные расчета определителя.

Также если использовать метод Гаусса для проверки точности расчета


определителя, то он будет возвращаеть true для матрицы 9х9 вне зависимости
от количества проверок и false для матрицы 10x10, это говорит о том,
точность сильно падает при размерности 10 и более.

11
Заключение

В результате выполнения теоретической работы была изучена история


возникновения матриц и операции над ними.

В результате выполнения практической работы был разработан и


протестирован шаблонный класс для работы с матрицами.

Матрицы используются во многих сферах деятельности, поэтому


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

12
Список литературы
1. Березкина Э. И. Математика древнего Китая / Отв. ред. Б. А.
Розенфельд. — М.: Наука, 1980. — С. 173-206. — 312 с.
2. Даан-Дальмедико А., Пейффер Ж. Пути и лабиринты. Очерки по
истории математики: Пер. с франц. — М.: Мир, 1986. — С. 397.

13
Приложение
main.cpp
#include <iostream>

#include "Utils.h"
#include "Matrix.h"

int main() {
srand(time(NULL));
setlocale(LC_ALL, "Russian");

TestMatrix test;

std::cout << test.determinantAccuracy(9, 100) <<


std::endl;

double* detTime = test.determinantTime(8, 1000);


std::cout << detTime[0] << ' ' << detTime[1] << ' '
<< std::endl;

try {
test.testMath(1000);
}
catch (MyException& ex) {
std::cout << ex.what();
}

Matrix<double> m1(3, 3);


m1(0, 0) = 2; m1(0, 1) = 5; m1(0, 2) = 7;
m1(1, 0) = 6; m1(1, 1) = 3; m1(1, 2) = 4;
m1(2, 0) = 5; m1(2, 1) = -2; m1(2, 2) = -3;
std::cout << m1.inverse();
}

matrix.h
#pragma once
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <iomanip>
#include <math.h>
class MyException : public std::exception {
public:
14
MyException(const char* msg) : exception(msg) {}
};

template <class T> class Matrix {


private:
T** matrix;
size_t rows, cols;

void clear();
T*& operator[](size_t);
public:
Matrix(size_t, size_t, const T& = T());
Matrix(const Matrix&);
~Matrix();

size_t getRows() { return rows; }


size_t getCols() { return cols; }

friend std::ostream& operator << (std::ostream& os,


const Matrix<T>& obj) {
for (size_t i = 0; i < obj.rows; i++) {
for (size_t j = 0; j < obj.cols; j++) {
std::cout << std::setw(3) <<
obj.matrix[i][j] << ' ';
}
std::cout << std::endl;
}
return os;
}

T& operator()(size_t, size_t);

Matrix operator*(const T);


Matrix operator/(const T);
Matrix operator*(const Matrix&);
Matrix operator+(const Matrix&);
Matrix operator-(const Matrix&);
Matrix operator*=(const T);
Matrix operator/=(const T);
Matrix operator*=(const Matrix&);
Matrix operator+=(const Matrix&);
Matrix operator-=(const Matrix&);
Matrix operator=(const Matrix&);

Matrix transposition();
15
double determinant();
double determinantAlgebraic();
double determinantGauss();

double minor(size_t, size_t);


double algebraicComplement(size_t, size_t);
Matrix<double> inverse();
};

template <typename T> Matrix<T>::Matrix(size_t rows,


size_t cols, const T& val) {
if (cols < 1 || rows < 1) {
MyException exception("Сonstructor failed,
invalid indices");
throw exception;
}
this->rows = rows;
this->cols = cols;

matrix = new T * [rows];


for (size_t i = 0; i < rows; i++) {
matrix[i] = new T[cols];

for (size_t j = 0; j < cols; j++) {


matrix[i][j] = val;
}
}
}
template <typename T> Matrix<T>::Matrix(const Matrix&
obj) {
rows = obj.rows;
cols = obj.cols;

matrix = new T * [rows];


for (size_t i = 0; i < rows; i++) {
matrix[i] = new T[cols];

for (size_t j = 0; j < cols; j++) {


matrix[i][j] = obj.matrix[i][j];
}
}
}
template <typename T> Matrix<T>::~Matrix() {
clear();
16
}

template <typename T> void Matrix<T>::clear() {


for (size_t i = 0; i < rows; i++) {
delete[] matrix[i];
}
delete[] matrix;
}

template <typename T> T& Matrix<T>::operator()(size_t


rows, size_t cols) {
if (rows < 0 || rows > this->rows) {
MyException exception("Invalid line number");
throw exception;
}
if (cols < 0 || cols > this->cols) {
MyException exception("Invalid column number");
throw exception;
}
return matrix[rows][cols];
}
template <typename T> T*& Matrix<T>::operator[](size_t
n) {
return matrix[n];
}
template <typename T> Matrix<T>
Matrix<T>::operator*(const T num) {
Matrix<T> tmp = *this;
tmp *= num;
return tmp;
}
template <typename T> Matrix<T>
Matrix<T>::operator/(const T num) {
Matrix<T> tmp = *this;
tmp /= num;
return tmp;
}
template <typename T> Matrix<T>
Matrix<T>::operator*(const Matrix& obj) {
Matrix<T> tmp = *this;
tmp *= obj;
return tmp;
}
template <typename T> Matrix<T> Matrix<T>::operator+
(const Matrix& obj) {
17
Matrix<T> tmp = *this;
tmp += obj;
return tmp;
}
template <typename T> Matrix<T> Matrix<T>::operator-
(const Matrix& obj) {
Matrix<T> tmp = *this;
tmp -= obj;
return tmp;
}
template <typename T> Matrix<T>
Matrix<T>::operator*=(const T num) {
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
matrix[i][j] *= num;
}
}
return *this;
}
template <typename T> Matrix<T>
Matrix<T>::operator/=(const T num) {
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
matrix[i][j] /= num;
}
}
return *this;
}
template <typename T> Matrix<T>
Matrix<T>::operator*=(const Matrix& obj) {
if (cols != obj.rows) {
MyException exception("Unsuitable dimensions");
throw exception;
}
Matrix<T> tmp(rows, obj.cols);

for (size_t i = 0; i < rows; i++) {


for (size_t j = 0; j < cols; j++) {
for (size_t k = 0; k < obj.rows; k++) {
tmp.matrix[i][j] += matrix[i][k] *
obj.matrix[k][j];
}
}
}
*this = tmp;
18
return *this;
}
template <typename T> Matrix<T>
Matrix<T>::operator+=(const Matrix& obj) {
if (rows != obj.rows) {
MyException exception("Unequals strings");
throw exception;
}
if (cols != obj.cols) {
MyException exception("Unequals columns");
throw exception;
}
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
matrix[i][j] += obj.matrix[i][j];
}
}
return *this;
}
template <typename T> Matrix<T> Matrix<T>::operator-
=(const Matrix& obj) {
if (rows != obj.rows) {
MyException exception("Unequals strings");
throw exception;
}
if (cols != obj.cols) {
MyException exception("Unequals columns");
throw exception;
}
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
matrix[i][j] -= obj.matrix[i][j];
}
}
return *this;
}
template <typename T> Matrix<T>
Matrix<T>::operator=(const Matrix& obj) {
clear();
new (this) Matrix(obj);
return *this;
}

template <typename T> Matrix<T>


Matrix<T>::transposition() {
19
Matrix<T> tmp(cols, rows);
for (size_t i = 0; i < cols; i++) {
for (size_t j = 0; j < rows; j++) {
tmp.matrix[i][j] = matrix[j][i];
}
}
return tmp;
}

template <typename T> double Matrix<T>::determinant() {


if (rows == 1 || rows == 2 || rows >= 10) {
return determinantAlgebraic();
}
else {
return determinantGauss();
}
}
template <typename T> double
Matrix<T>::determinantAlgebraic() {
if (rows != cols) {
MyException exception("Non-square matrix");
throw exception;
}

if (rows == 1) {
return matrix[0][0];
}
else if (rows == 2) {
return matrix[0][0] * matrix[1][1] - matrix[0]
[1] * matrix[1][0];
}
else {
double d = 0;
for (size_t k = 0; k < rows; k++) {
Matrix<T> b(rows - 1, rows - 1);
for (size_t i = 1; i < rows; i++) {
for (size_t j = 0; j < rows; j++) {
if (j == k) {
continue;
}
else if (j < k) {
b(i - 1, j) = matrix[i][j];
}
else {
b(i - 1, j - 1) = matrix[i][j];
20
}
}
}
d += (k % 2 == 0 ? 1 : -1) * matrix[0][k] *
b.determinantAlgebraic();
}
return d;
}
}
template <typename T> double
Matrix<T>::determinantGauss() {
if (rows != cols) {
MyException exception("Non-square matrix");
throw exception;
}

const double EPS = 1e-9;


double det = 1;

Matrix<double> tmp(rows, cols);


for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < rows; j++) {
tmp(i, j) = matrix[i][j];
}
}

for (size_t i = 0; i < rows; ++i) {


size_t k = i;
for (size_t j = i + 1; j < rows; ++j) {
if (fabs(tmp(j, i)) > fabs(tmp(k, i))) {
k = j;
}
}
if (fabs(tmp(k, i)) < EPS) {
det = 0;
break;
}
std::swap(tmp[i], tmp[k]);
if (i != k) {
det = -det;
}
det *= tmp(i, i);
for (size_t j = i + 1; j < rows; ++j) {
tmp(i, j) /= tmp(i, i);
}
21
for (size_t j = 0; j < rows; ++j) {
if (j != i && fabs(tmp(j, i)) > EPS) {
for (size_t k = i + 1; k < rows; ++k) {
tmp(j, k) -= tmp(i, k) * tmp(j, i);
}
}
}
}
return det;
}

template <typename T> double Matrix<T>::minor(size_t


rows, size_t cols) {
if (this->rows != this->cols) {
MyException exception("Non-square matrix");
throw exception;
}

size_t n = this->rows - 1;
Matrix<T> tmp(n, n);

for (size_t i = 0; i < n + 1; i++) {


if (i == rows) {
continue;
}
for (size_t j = 0; j < n + 1; j++) {
if (j == cols) {
continue;
}
if (i < rows && j < cols) {
tmp(i, j) = matrix[i][j];
}
else if (i < rows && j > cols) {
tmp(i, j - 1) = matrix[i][j];
}
else if (i > rows && j < cols) {
tmp(i - 1, j) = matrix[i][j];
}
else {
tmp(i - 1, j - 1) = matrix[i][j];
}
}
}
return tmp.determinant();
}
22
template <typename T> double
Matrix<T>::algebraicComplement(size_t rows, size_t
cols) {
return ((cols + rows) % 2 == 0 ? 1 : -1) *
minor(rows, cols);
}
template <typename T> Matrix<double>
Matrix<T>::inverse() {
if (rows != cols) {
MyException exception("Non-square matrix");
throw exception;
}
if (determinant() == 0) {
MyException exception("Degenerate matrix");
throw exception;
}

Matrix<double> tmp(rows, cols);


if (rows && cols == 1) {
tmp(0, 0) = 1 / matrix[0][0];
return tmp;
}

for (size_t i = 0; i < rows; i++) {


for (size_t j = 0; j < cols; j++) {
tmp(i, j) = algebraicComplement(i, j);
}
}
return tmp.transposition() / determinant();
}

#endif

Utils.h
#pragma once
#include <iostream>
#include <time.h>

#include "Matrix.h"

class Timer {
private:
clock_t startTime;
clock_t endTime;
23
public:
Timer();
void start();
void stop();
double getTimeMilliSec();
};

class TestMatrix {
private:
bool compare(Matrix<double>, Matrix<double>);
void rnd(Matrix<double>*);
public:
bool testMath(long long);
double* determinantTime(int, long long);
bool determinantAccuracy(int, long long);
};

Utils.cpp
#include "Utils.h"

Timer::Timer() {
startTime = -1;
endTime = -1;
}
void Timer::start() {
startTime = clock();
endTime = -1;
}
void Timer::stop() {
endTime = clock();
}
double Timer::getTimeMilliSec()
{
return (double)(endTime - startTime) * 1000 /
CLOCKS_PER_SEC;
}

bool TestMatrix::compare(Matrix<double> myMatrix1,


Matrix<double> myMatrix2) {
if (myMatrix1.getRows() != myMatrix2.getRows()) {
return false;
}
if (myMatrix1.getCols() != myMatrix2.getCols()) {
24
return false;
}

for (size_t i = 0; i < myMatrix1.getRows(); i++) {


for (size_t j = 0; j < myMatrix1.getCols(); j+
+) {
if (abs(myMatrix1(i, j) - myMatrix2(i, j))
> 1e-8) {
return false;
}
}
}

return true;
}
void TestMatrix::rnd(Matrix<double>* myMatrix) {
for (size_t i = 0; i < myMatrix->getRows(); i++) {
for (size_t j = 0; j < myMatrix->getCols(); j+
+) {
(*myMatrix)(i, j) = ((double)rand() /
RAND_MAX) * 10 - 5;
}
}
}

bool TestMatrix::testMath(long long iterations) {


for (int k = 0; k < iterations; k++) {
size_t n = rand() % 5 + 1;

Matrix<double> A(n, n);


rnd(&A);

Matrix<double> E(n, n);


for (size_t i = 0; i < E.getCols(); i++) {
E(i, i) = 1.0;
}

if (!compare(A * A.inverse(), E)) {


MyException exception("Fail");
throw exception;
std::cout << E << std::endl;
}
}
return true;
}
25
double* TestMatrix::determinantTime(int sizeMatrix,
long long iterations) {
Matrix<double>* m1 = new Matrix<double>(sizeMatrix,
sizeMatrix);

Timer* timer = new Timer();


double time[2] = { 0 };

for (int i = 0; i < iterations; i++) {


rnd(m1);

timer->start();
m1->determinantAlgebraic();
timer->stop();
time[0] += timer->getTimeMilliSec();

timer->start();
m1->determinantGauss();
timer->stop();
time[1] += timer->getTimeMilliSec();
}

return time;
}

bool TestMatrix::determinantAccuracy(int sizeMatrix,


long long iterations) {
Matrix<double> m1(sizeMatrix, sizeMatrix);

for (int i = 0; i < iterations; i++) {


rnd(&m1);
double det = m1.determinantAlgebraic();
double det2 = m1.determinantGauss();
if (abs(det - det2) > 1e-7) {
printf("%.10f %.10f\n", det, det2);
return false;
}
}
return true;
}

26

Вам также может понравиться