Добавил:
CanyonE
СПбГУТ * ИКСС * Программная инженерия
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Решения лабораторных работ (местами есть ошибки) / Lab1_Matrix
.cpp#include <cmath>
#include <iostream>
#include <stdexcept>
using std::cin;
using std::cout;
using std::endl;
// Класс «Матрица»
class SimpleMatrix {
private:
// Количество строк
size_t n_;
// Количество столбцов
size_t m_;
// Указатель на указатель
double **values_ = nullptr;
public:
// Конструкторы
// Для матрицы N (строк) на M (столбцов)
explicit SimpleMatrix(size_t n, size_t m) : n_(n), m_(m) {
if (n > 0 && m > 0) {
values_ = new double *[n]; // Выделяем память для строк
for (size_t i = 0; i < n; ++i) {
values_[i] = new double[m] {0}; // Для столбцов
}
}
}
// Для квадратной (м. б. единичной) матрицы
explicit SimpleMatrix(size_t n, bool isIdentity = false) : n_(n), m_(n) {
if (n > 0 && m_ > 0) {
values_ = new double *[n]; // Выделяем память для строк
for (size_t i = 0; i < n; ++i) {
values_[i] = new double[m_] {0},
values_[i][i] = 1; // Для столбцов; элементы главной диагонали = 1
}
}
}
// Конструктор копирования
SimpleMatrix(const SimpleMatrix &arg) : n_(arg.n_), m_(arg.m_) {
values_ = new double *[n_]; // Выделяем память для строк
for (size_t i = 0; i < n_; ++i) {
values_[i] = new double[m_]; // Для столбцов
std::copy(arg.values_[i], arg.values_[i] + m_, values_[i]); // Копируем очередную строку из arg в текущую
}
}
// Оператор копирования
SimpleMatrix &operator=(const SimpleMatrix &arg) {
SimpleMatrix temp(arg); // Создаем копию arg
swap(*this, temp); // Меняем местами уже существующий this и копию arg; temp после return уничтожится
return *this;
}
// Конструктор перемещения
SimpleMatrix(SimpleMatrix &&arg) noexcept {
values_ = arg.values_, n_ = arg.n_, m_ = arg.m_; // Перемещаем данные из arg
arg.values_ = nullptr, arg.n_ = arg.m_ = 0; // Заполняем поля arg 'нулевыми' значениями
}
// Оператор перемещения
SimpleMatrix &operator=(SimpleMatrix &&arg) noexcept {
if (this != &arg) { // Если мы не пытаемся переместить себя в себя так: MyObject = std::move(MyObject);
swap(*this, arg); // Меняем местами this и arg
if (arg.values_) { // Освобождаем память arg (которая ранее была в this), если она имелась
for (size_t i = 0; i < arg.n_; ++i) {
delete[] arg.values_[i];
}
delete[] arg.values_;
arg.values_ = nullptr, arg.n_ = arg.m_ = 0; // Заполняем поля arg 'нулевыми' значениями
}
}
return *this;
}
// Деструктор
virtual ~SimpleMatrix() {
for (size_t i = 0; i < n_; ++i) {
delete[] values_[i];
}
delete[] values_; // Если values_ = nullptr, то delete[] не приведет к ошибке
}
// Очистка матрицы
void clear() {
for (size_t i = 0; i < n_; ++i) {
delete[] values_[i];
}
delete[] values_;
values_ = nullptr, n_ = m_ = 0;
}
// Получение строки матрицы по индексу (не вызывает исключения)
double *operator[](size_t idx) {
return values_[idx]; // Возвращаем строку (Обращение к элементу строки i столбца j: values_[idx][idx2])
}
// Число строк матрицы
size_t N() const { return n_; }
// Число столбцов матрицы
size_t M() const { return m_; }
// Сложение матриц
SimpleMatrix operator+(const SimpleMatrix &arg) const noexcept(false) {
if (n_ == arg.n_ && m_ == arg.m_) { // Сложение возможно, если только размеры матриц равны
SimpleMatrix result(*this); // Копируем данные из *this в result (конструктор копирования)
for (size_t i = 0; i < n_; ++i) {
for (size_t j = 0; j < m_; ++j) {
result.values_[i][j] += arg.values_[i][j]; // В result копия данных this складывается с данными arg
}
}
return result;
}
throw std::invalid_argument("N != ARG.N || M != ARG.M");
}
// Вычитание матриц
SimpleMatrix operator-(const SimpleMatrix &arg) const {
return ( *this + ( -arg ) ); // Используем уже существующий оператор сложения с матрицей
}
// Смена знака элементов матрицы
SimpleMatrix operator-() const {
SimpleMatrix result(*this); // Копируем данные из *this в result (конструктор копирования)
for (size_t i = 0; i < n_; ++i) {
for (size_t j = 0; j < m_; ++j) {
result.values_[i][j] = -result.values_[i][j];
}
}
return result;
}
// Умножение матриц
SimpleMatrix operator*(const SimpleMatrix &arg) const noexcept(false) {
if (m_ == arg.n_) { // Если число стб. матрицы this совпадает с числом стр. матрицы arg, то умножение возможно
SimpleMatrix result(this->n_, arg.m_); // Конструктор по размерам
for (size_t i = 0; i < n_; ++i) {
for (size_t j = 0; j < arg.m_; ++j) {
for (size_t k = 0; k < m_; ++k) {
result.values_[i][j] += values_[i][k] * arg.values_[k][j];
}
}
}
return result;
}
throw std::invalid_argument("The number of columns of matrix A is not equal to the number of rows of matrix B");
}
// Умножение всех элементов матрицы на заданное число
SimpleMatrix operator*(const double &d) const {
SimpleMatrix result(*this); // Копируем данные из *this в result (конструктор копирования)
for (size_t i = 0; i < n_; ++i) {
for (size_t j = 0; j < m_; ++j) {
result.values_[i][j] *= d;
}
}
return result;
}
// Деление всех элементов матрицы на заданное число
SimpleMatrix operator/(const double &d) const {
return ( *this * ( 1. / d ) ); // Используем уже существующий оператор умножения на число
}
// Сумма элементов k-той строки
double sumString(size_t k) const noexcept(false) {
if (k >= 0 && k < n_) { // Если k-тая строка имеется, то вычисляем сумму
double s = 0;
for (size_t j = 0; j < m_; ++j) {
s += values_[k][j];
}
return s;
}
throw std::out_of_range("SimpleMatrix. Method sumString. Out of range");
}
// Сумма элементов k-того столбца
double sumColumn(size_t k) const noexcept(false) {
if (k >= 0 && k < m_) { // Если k-тый столбец имеется, то вычисляем сумму
double s = 0;
for (size_t i = 0; i < n_; ++i) {
s += values_[i][k];
}
return s;
}
throw std::out_of_range("SimpleMatrix. Method sumColumn. Out of range");
}
// Транспонирование матрицы
SimpleMatrix transpose() const {
SimpleMatrix result(m_, n_); // При транспонировании n становится m, m становится n
for (size_t i = 0; i < n_; ++i) {
for (size_t j = 0; j < m_; ++j) {
result.values_[j][i] = values_[i][j];
}
}
return result;
}
// Применение функции func к каждому элементу матрицы
SimpleMatrix doForEach(double (*func)(double)) const {
SimpleMatrix result(*this); // Копируем данные из *this в result (конструктор копирования)
for (size_t i = 0; i < n_; ++i) {
for (size_t j = 0; j < m_; ++j) {
result.values_[i][j] = func(result.values_[i][j]); // Применяем к каждому элементу функцию func
}
}
return result;
}
// Равны ли две матрицы?
bool operator==(const SimpleMatrix &arg) const {
if (n_ != arg.n_ && m_ != arg.m_) {
return false;
}
for (size_t i = 0; i < n_; ++i) {
for (size_t j = 0; j < m_; ++j) {
if (this->values_[i][j] != arg.values_[i][j]) {
return false;
}
}
}
return true;
}
// Не равны ли две матрицы?
bool operator!=(const SimpleMatrix &arg) const {
return !( *this == arg );
}
// Оператор приведения к типу bool
explicit operator bool() {
return n_ != 0 && m_ != 0;
}
// Дружественный оператор для вывода матрицы в выходной поток os (cout, ...)
friend std::ostream &operator<<(std::ostream &os, const SimpleMatrix &arg) {
for (size_t i = 0; i < arg.n_; ++i) {
os << arg.values_[i][0];
for (size_t j = 1; j < arg.m_; ++j) {
os << ' ' << arg.values_[i][j];
}
os << '\n';
}
return os;
}
friend void swap(SimpleMatrix &first, SimpleMatrix &second) noexcept {
std::swap(first.values_, second.values_);
std::swap(first.m_, second.m_);
std::swap(first.n_, second.n_);
}
};
int main() {
const size_t N1 = 2, N2 = 5;
// Создание матриц
SimpleMatrix massA(N1, N2), massB(N2, N1);
// Вывод матрицы и её размеров
cout << "Matrix A:\n" << massA << "(size: " << massA.N() << " x " << massA.M() << ')' << endl;
cout << "Matrix B:\n" << massB << "(size: " << massB.N() << " x " << massB.M() << ')' << endl << endl;
// Заполнение матрицы
for (size_t i = 0; i < N1; ++i) {
for (size_t j = 0; j < N2; ++j) {
massA[i][j] = rand() % 100;
massB[j][i] = rand() % 100;
}
}
// Вывод матрицы
cout << "Matrix A:\n" << massA << "(size: " << massA.N() << " x " << massA.M() << ')' << endl;
cout << "Matrix B:\n" << massB << "(size: " << massB.N() << " x " << massB.M() << ')' << endl << endl;
// Конструктор копирования
SimpleMatrix massC(massB);
cout << "1. Copy constructor:" << endl;
cout << "Matrix B:\n" << massB << "(size: " << massB.N() << " x " << massB.M() << ')' << endl;
cout << "Matrix C:\n" << massC << "(size: " << massC.N() << " x " << massC.M() << ')' << endl << endl;
// Оператор копирования
massC = massA;
cout << "2. Copy assignment:" << endl;
cout << "Matrix A:\n" << massA << "(size: " << massA.N() << " x " << massA.M() << ')' << endl;
cout << "Matrix C:\n" << massC << "(size: " << massC.N() << " x " << massC.M() << ')' << endl << endl;
// Конструктор перемещения
SimpleMatrix massD(std::move(massB));
cout << "3. Move constructor:" << endl;
cout << "Matrix B:\n" << massB << "(size: " << massB.N() << " x " << massB.M() << ')' << endl;
cout << "Matrix D:\n" << massD << "(size: " << massD.N() << " x " << massD.M() << ')' << endl << endl;
// Оператор перемещения
massD = std::move(massA);
cout << "4. Move assignment:" << endl;;
cout << "Matrix A:\n" << massA << "(size: " << massA.N() << " x " << massA.M() << ')' << endl;
cout << "Matrix D:\n" << massD << "(size: " << massD.N() << " x " << massD.M() << ')' << endl << endl;
// Очистка матриц
cout << "Matrix C (size before clear): " << massC.N() << " x " << massC.M() << endl << endl;
massC.clear();
cout << "Matrix C (size after clear): " << massC.N() << " x " << massC.M() << endl << endl;
// Умножение и деление матрицы на число
massC = ( massD * 5 ) / 4;
cout << "New Matrix C:\n" << massC << "(size: " << massC.N() << " x " << massC.M() << ')' << endl;
cout << "New Matrix D:\n" << massD << "(size: " << massD.N() << " x " << massD.M() << ')' << endl << endl;
// Сложение и вычитание матриц
cout << "Matrix C + Matrix D:\n" << ( massC + massD ) << "(size: " << massC.N() << " x " << massC.M() << ')'
<< endl;
cout << "Matrix C - Matrix D:\n" << ( massC - massD ) << "(size: " << massC.N() << " x " << massC.M() << ')' << endl
<< endl;
// Транспонирование матрицы
cout << "Matrix D (before transpose):\n" << massD << "(size: " << massD.N() << " x " << massD.M() << ')' << endl;
massD = massD.transpose();
cout << "Matrix D (after transpose):\n" << massD << "(size: " << massD.N() << " x " << massD.M() << ')' << endl
<< endl;
massD = massD.transpose();
// Умножение матриц
SimpleMatrix temp = massD * massD.transpose();
cout << "Matrix D * (Matrix D transpose):\n" << temp << "(size: " << temp.N() << " x " << temp.M() << ')' << endl
<< endl;
// Сумма элементов строки
cout << "Sum string(0): " << temp.sumString(0) << endl;
cout << "Sum string(1): " << temp.sumString(1) << endl;
// Сумма элементов столбца
cout << "Sum column(0): " << temp.sumColumn(0) << endl;
cout << "Sum column(1): " << temp.sumColumn(1) << endl << endl;
// Применение различных функций к каждому элементу матрицы
cout << "Matrix E:\n" << temp << endl;
cout << "sqrt(for each elem in Matrix E):\n" << temp.doForEach(sqrt) << endl;
cout << "sin(for each elem in Matrix E):\n" << temp.doForEach(sin) << endl;
cout << "cos(for each elem in Matrix E):\n" << temp.doForEach(cos) << endl;
}
Соседние файлы в папке Решения лабораторных работ (местами есть ошибки)