Форум программистов, компьютерный форум CyberForum.ru

Класс матриц - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 83, средняя оценка - 4.96
Gabberr
 Аватар для Gabberr
101 / 101 / 17
Регистрация: 13.10.2009
Сообщений: 402
13.12.2010, 18:29     Класс матриц #1
Пытаюсь написать класс матриц.Никак не удаётся перегрузить оператор = .
Выдаёт :
ambiguous overload for 'operator=' in 'k = b'
candidates are: Matrix Matrix::operator=(Matrix)
Matrix& Matrix::operator=(const Matrix&)

Помогите, пожалуйста,разобраться

вот сам класс
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Matrix
{
    private:
            int nstr,nstl;
            int **a;
    public:
            Matrix (int m,int n);  
            Matrix (int m,int n,int *b);       
            ~Matrix ();
            Matrix operator + (Matrix b);
            Matrix operator * (Matrix b);
            Matrix operator * (int c);
            Matrix operator = (Matrix b);
            Matrix operator += (Matrix b);
            Matrix (const Matrix &T);
            Matrix & operator = (const Matrix &);
            void Print ();
};
вот методы

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "Matrix.h"
#include <iostream.h>
#include <iomanip.h>
Matrix::Matrix (int m,int n)
{    
     nstr=m;
     nstl=n; 
     a=new int *[nstr]; 
     for (int j=0;j<nstr;j++)
     {
        a[j]=new int[nstl]; 
        for (int i=0;i<nstl;i++)
           a[j][i]=0;     
     }
}
Matrix::Matrix (int m,int n,int *b)
{
     nstr=m;
     nstl=n; 
     int k=0;
     a=new int *[nstr]; 
     for (int j=0;j<nstr;j++)
     {
        a[j]=new int[nstl]; 
        for (int i=0;i<nstl;i++)
        {
           a[j][i]=b[k];
           k++;
        }       
     }
}           
Matrix::~Matrix()
{
    for (int i=0;i<nstr;i++)
       delete []a;             
}
Matrix::Matrix (const Matrix& T)
{ 
    nstr=T.nstr;
    nstl=T.nstl;           
    for (int i=0;i<T.nstr;i++)
       for (int j=0;j<T.nstl;j++)
          a[i][j]=T.a[i][j];                
}
Matrix & Matrix::operator = (const Matrix & T)
{
   if (this == &T) 
      return *this;
   else
   {
       delete a;
       nstr=T.nstr;
       nstl=T.nstl;
       a=new int *[nstr]; 
     for (int j=0;j<nstr;j++)
     {
        a[j]=new int[nstl]; 
        for (int i=0;i<nstl;i++)
           a[j][i]=T.a[i][j];     
     }
     
     
 
       return *this; 
   }        
}
void Matrix::Print ()
{
    for (int i=0;i<nstr;i++)
    {
       for (int j=0;j<nstl;j++)  
          cout<<setw(3)<<a[i][j];
       cout<<endl;   
    }           
}
и вот main
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <cstdlib>
#include <iostream.h>
#include "Matrix.h"
int main()
{
    int c[10]={1,2,3,4,5,6,7,8,9,10};
    Matrix b(5,2,c),k(5,2);
    k=b;
    k.Print();
    system("PAUSE");
    return 0;
}
ошибка в 8 строке ф-ии main
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.12.2010, 18:29     Класс матриц
Посмотрите здесь:

Класс матриц C++
C++ Класс Матриц ( исправьте Ошибки плз)
C++ Класс матриц
C++ Класс матриц
C++ Класс матриц с арифметическими операциями С++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
13.12.2010, 19:08     Класс матриц #2
Вот как надо:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Matrix
{
    private:
            int nstr,nstl;
            int **a;
    public:
            Matrix (int m,int n);  
            Matrix (int m,int n,int *b);       
            ~Matrix ();
            Matrix operator + (const Matrix& b) const {Matrix rv(this); rv += b; return rv;};
            Matrix operator * (const Matrix& b) const;
            Matrix operator * (int c) const;
            Matrix& operator += (const Matrix& b);
            Matrix (const Matrix &src);
            Matrix & operator = (const Matrix &val);
            void Print ();
};
Gabberr
 Аватар для Gabberr
101 / 101 / 17
Регистрация: 13.10.2009
Сообщений: 402
14.12.2010, 08:59  [ТС]     Класс матриц #3
оказывается просто был лишний метод
Matrix operator = (Matrix b);

Добавлено через 5 часов 51 минуту
что означает

Цитата Сообщение от Nick Alte Посмотреть сообщение
C++
1
Matrix operator + (const Matrix& b) const {Matrix rv(this); rv += b; return rv;};

я написал перегрузку + ,но что-то опять не то ,объясние плиз!


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
Matrix &Matrix::operator + (const Matrix & b)
{
     Matrix s;  
     if (nstr == b.nstr && nstl == b.nstl)
        {
           for (int i=0;i<nstr;i++)
              for (int j=0;j<nstl;j++)
                 s.a[i][j]=a[i][j]+b.a[i][j];
           return s;
        }
     else 
        error(2);         
}

может компилятор devc++ пора менять на vs или на gcc кодить ?

Добавлено через 13 минут
ааа я дико ступил,не задал размеры матрицы)))

Добавлено через 7 часов 37 минут
написал перегрузку,компилятор ошибок не выдаёт,но вылазит ошибка microsoft

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
Matrix & Matrix::operator + (const Matrix & b)
{  
   if (nstr == b.nstr && nstl == b.nstl)
        {
           Matrix s(nstr,nstl); 
           for (int i=0;i<nstr;i++)
              for (int j=0;j<nstl;j++)
                 s.a[i][j]=a[i][j]+b.a[i][j];
           return s;
        }
     else 
        error(2);         
}

как же все таки перегрузить + ?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
15.12.2010, 00:25     Класс матриц #4
Вроде функция написана верно, смотрите в другом месте, может где-то что-то не инициализировано или где-то выход за границы массива.
lemegeton
 Аватар для lemegeton
2909 / 1338 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
15.12.2010, 02:33     Класс матриц #5
Не лишним, не лишним. Перегружайте =, [] (в двух видах -- const и обычный). Пригодится.
Цитата Сообщение от Gabberr Посмотреть сообщение
Matrix & Matrix::operator = (const Matrix & T)
{
* *if (this == &T)
* * * return *this;
* *else
* *{
* * * *delete a; // неправильно удалили двойной массив.
* * * *nstr=T.nstr;
* * * *nstl=T.nstl;
* * * *a=new int *[nstr];
* * *for (int j=0;j<nstr;j++)
* * *{
* * * * a[j]=new int[nstl];
* * * * for (int i=0;i<nstl;i++)
* * * * * *a[j][i]=T.a[i][j]; * *
* * *}
return *this;
* *} * * * *
}
Цитата Сообщение от Gabberr Посмотреть сообщение
Matrix::~Matrix()
{
* * for (int i=0;i<nstr;i++) // сколько-сколько раз вы удаляете одно и то же?!
* * * *delete []a; * * * * * * //
}
Добавлено через 1 минуту
И там и там должно быть что-то вроде
C++
1
2
3
for (int i=0;i<nstr;i++)
     delete [] a[i];
delete [] a;
Добавлено через 3 минуты
Попробуйте,
посмотрите мой вариант
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <iomanip>
 
using namespace std;
 
class Matrix
{
protected:
        double** _data;
        unsigned int _size;
public:
        Matrix(void) : _data(0), _size(0) {}
        Matrix(unsigned int size) : _size(size), _data(0)
        {
                if (_size>0)
                {
                        _data = new double*[_size];
                        for (int i=0; i<_size; i++)
                                _data[i] = new double[_size];
                }
        }
        Matrix(const Matrix& other)
        {
                Matrix(other.size());
                for (int i=0; i<_size; i++)
                for (int j=0; j<_size; j++)
                        _data[i][j] = other._data[i][j];
        }
 
        const unsigned int size() const { return _size; }
        double* operator[](int i) { return _data[i]; }
        double& at(int i, int j) { return _data[i][j]; }
 
        Matrix& operator=(const Matrix& other)
        {
                if (this!=&other)
                {
                        for (int i=0; i<_size; i++)
                                delete [] _data[i];
                        delete [] _data;
                        _size = other.size();
                        if (_size>0)
                        {
                                _data = new double*[_size];
                                for (int i=0; i<_size; i++)
                                {
                                        _data[i] = new double[_size];
                                        for (int j=0; j<_size; j++)
                                                _data[i][j] = other._data[i][j];
                                }
                        }
                }
                return *this;
        }
 
        ~Matrix()
        {
                for (int i=0; i<_size; i++)
                        delete [] _data[i];
                delete [] _data;
        }
};
. Вдруг что новое почерпнете?

Добавлено через 4 минуты
Нашел у себя еще более подходящее под вашу задачу.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <exception>
#include <stdexcept>
 
using namespace std;
 
class Array
{
protected:
        int** _data;
        int _cols, _rows;
public:
        Array(void) : _data(0), _rows(0),_cols(0) {};
        Array(int rows, int cols, bool fill=false, int filler=0)
                : _rows(rows), _cols(cols), _data(0)
        {
                _data = new int* [_rows];
                for (int i=0; i<_rows; i++)
                {
                        _data[i] = new int[_cols];
                        if (fill)
                                for (int j=0; j<_cols; j++)
                                        _data[i][j] = filler;
                }
        }
 
        Array(const Array& other) :
                _cols(other.cols()),
                _rows(other.rows())
        {
                _data = new int* [_rows];
                for (int i=0; i<_rows; i++)
                {
                        _data[i] = new int[_cols];
                        for (int j=0; j<_cols; j++)
                                _data[i][j] = other._data[i][j];
                }
        }
 
        const Array transpon() const
        {
                Array C(_cols, _rows);
                for (int i=0; i<_cols; i++)
                        for (int j=0; j<_rows; j++)
                                C[i][j] = _data[j][i];
                return C;
        }
 
        const Array operator+(const Array& other) const
        {
                if ((_cols != other.cols()) || (_rows != other.rows()))
                        throw out_of_range("Multiplied matrixes do not have same number of cols and rows.");
                Array C(_rows, _cols);
                for (int i=0; i<C.rows(); i++)
                        for (int j=0; j<C.cols(); j++)
                                C._data[i][j] = _data[i][j] + other._data[i][j];
                return C;
        }
 
        const Array operator*(const Array& other) const
        {
                if (_cols != other.rows())
                        throw out_of_range("Multiplied matrixes do not have same number of cols and rows.");
                Array C(_rows, other.cols(), true);
                for (int i=0; i<C.rows(); i++)
                        for (int j=0; j<C.cols(); j++)
                                for (int k=0; k<_cols; k++)
                                C[i][j] += _data[i][k]*other._data[k][j];
                return C;
        }
 
        Array& operator= (const Array& other)
        {
                if (this!=&other)
                {
                        if (_data!=0)
                        {
                                for (int i=0; i<_rows; i++)
                                        delete [] _data[i];
                                delete [] _data;
                        }
                        _rows = other.rows();
                        _cols = other.cols();
 
                        _data = new int* [_rows];
                        for (int i=0; i<_rows; i++)
                                _data[i] = new int[_cols];
 
                        for (int i=0; i<_rows; i++)
                                for (int j=0; j<_cols; j++)
                                        _data[i][j] = other._data[i][j];
                }
                return *this;
        }
 
        friend ostream& operator<< (ostream& o, const Array& a)
        {
                for (int i=0; i<a._rows; i++)
                {
                        for (int j=0; j<a._cols; j++)
                                o << setw(4) << a._data[i][j];
                        o << endl;
                }
                return o;
        }
 
        void fill_random()
        {
                for (int i=0; i<_rows; i++)
                        for (int j=0; j<_cols; j++)
                                _data[i][j] = rand()%100+1;
        }
 
        int* operator[](int i) { return _data[i]; }
        int& at(int i, int j) { return _data[i][j]; }
 
        const int cols() const { return _cols; }
        const int rows() const { return _rows; }
 
        ~Array()
        {
                if (_data!=0)
                {
                        for (int i=0; i<_rows; i++)
                                delete [] _data[i];
                        delete [] _data;
                }
        }
};
 
// пример
int main()
{
        srand(static_cast<unsigned int>(time(0)));
 
        Array a(5, 5);
        a.fill_random();
        cout << a << endl;
 
        int* max_cols = new int[a.cols()];
        for (int i=0; i<a.cols(); i++)
        {
                max_cols[i] = a[i][0];
                for (int j=1; j<a.rows(); j++)
                        if (max_cols[i] < a[i][j])
                                max_cols[i] = a[i][j];
                cout << setw(4) << max_cols[i];
        }
        cout << endl << endl;
 
        int min = max_cols[0];
        for (int i=1; i<a.cols(); i++)
                if (min > max_cols[i])
                        min = max_cols[i];
 
        cout << setw(4) << min << endl;
        delete [] max_cols;
        Array x(3, 3, true, 1);
        Array y(3, 3, true, 1);
        Array z(3, 5);
        z.fill_random();
        cout << (x*y) << endl;
        cout << (x+y) << endl;
        cout << z << endl << z.transpon() << endl;
 
        return 0;
}
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2293 / 1663 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
15.12.2010, 03:03     Класс матриц #6
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <cassert>
#include <cstddef>
 
template<typename T>
class matrix {
  class row {
    friend class matrix;
 
    row(T* first_cell_in_row, std::size_t size);
 
    T*          first_cell_in_row;
    std::size_t size;
 
  public:
          T& operator[] (std::size_t index);
    const T& operator[] (std::size_t index) const;
  };
 
  T*          the_array;
  std::size_t row_count;
  std::size_t col_count;
 
public:
  matrix(std::size_t row_count, std::size_t col_count);
  matrix(const matrix& other);
 
  ~matrix() { delete [] the_array; }
 
  std::size_t rowCount() const { return row_count; }
  std::size_t colCount() const { return col_count; }
 
  matrix& operator= (const matrix& other);
 
        row operator[] (std::size_t index);
  const row operator[] (std::size_t index) const;
};
 
template<typename T>
matrix<T>::row::row(T* first_cell_in_row, std::size_t size)
: first_cell_in_row(first_cell_in_row)
, size             (size) {
}
 
template<typename T>
T& matrix<T>::row::operator[] (std::size_t index) {
  assert(index < size);
 
  return first_cell_in_row[index];
}
 
template<typename T>
const T& matrix<T>::row::operator[] (std::size_t index) const {
  assert(index < size);
 
  return first_cell_in_row[index];
}
 
template<typename T>
matrix<T>::matrix(std::size_t row_count, std::size_t col_count)
: row_count(row_count)
, col_count(col_count)
, the_array(new T[row_count * col_count]){
  for (std::size_t i = 0; i < rowCount() * colCount(); ++i)
    the_array[i] = T();
}
 
template<typename T>
matrix<T>::matrix(const matrix& other)
: row_count(other.rowCount())
, col_count(other.colCount())
, the_array(new T[other.rowCount() * other.colCount()]) {
  for (std::size_t i = 0; i < rowCount() * colCount(); ++i)
    the_array[i] = other.the_array[i];
}
 
template<typename T>
matrix<T>& matrix<T>::operator= (const matrix& other) {
  T* the_new_array = new T[other.rowCount() * other.colCount()];
 
  for (std::size_t i = 0; i < rowCount() * colCount(); ++i)
    the_new_array[i] = other[i];
 
  delete [] the_array;
 
  the_array = the_new_array;
  row_count = other.row_count;
  col_count = other.col_count;
}
 
template<typename T>
typename matrix<T>::row matrix<T>::operator[] (std::size_t index) {
  assert(index < rowCount());
 
  return row(the_array + (colCount() * index), colCount());
}
 
template<typename T>
const typename matrix<T>::row matrix<T>::operator[] (std::size_t index) const {
  assert(index < rowCount());
 
  return row(the_array + (colCount() * index), colCount());
}
 
template<typename T>
const matrix<T> operator+ (const matrix<T>& lhs, const matrix<T>& rhs) {
  assert(lhs.rowCount() == rhs.rowCount() && 
         lhs.colCount() == rhs.colCount());
  
  matrix<T> result(lhs.rowCount(), lhs.colCount());
 
  for (std::size_t i = 0; i < result.rowCount() * result.colCount(); ++i)
        result.the_array[i] = lhs.the_array[i] + rhs.the_array[i];
 
  return result;
}
 
template<typename T>
const matrix<T> operator- (const matrix<T>& lhs, const matrix<T>& rhs) {
  assert(lhs.rowCount() == rhs.rowCount() && 
         lhs.colCount() == rhs.colCount());
  
  matrix<T> result(lhs.rowCount(), lhs.colCount());
 
  for (std::size_t i = 0; i < result.rowCount() * result.colCount(); ++i)
        result.the_array[i] = lhs.the_array[i] - rhs.the_array[i];
 
  return result;
}
 
template<typename T>
const matrix<T> operator* (const matrix<T>& lhs, const matrix<T>& rhs) {
  assert(lhs.colCount() == rhs.rowCount());
  
  matrix<T> result(lhs.rowCount(), rhs.colCount());
 
  for (std::size_t i = 0; i < result.rowCount(); ++i)
    for (std::size_t j = 0; j < result.colCount(); ++j)
      for (std::size_t k = 0; k < lhs.colCount(); ++k)
        result[i][j] += lhs[i][k] * rhs[k][j];
 
  return result;
}
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
15.12.2010, 22:56     Класс матриц #7
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Тоже недавно писал класс матриц. Поскольку ещё не дошёл до шаблонных классов, пока так. Писал чисто для себя, поэтому реализовано, так сказать, с любовью Писал для изучения перегрузки операций, поэтому основной упор на этом, но присутствуют и полезные функции нахождения детерминанта, ранга, а так же взятия обратной матрицы. Ну и плюс полная закомментированность класса, что тоже радует)))

Row.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef ROW_H
#define ROW_H
 
#include <iostream>
 
class Row
{
private:
    double *_row;
    unsigned _size;
 
public:
    Row();
    Row(unsigned, double = 0.0);
    Row(const Row &);
    ~Row();
 
    unsigned size() const;
 
    void resize(unsigned = 1, double = 0.0);
 
    double &operator[](unsigned);
    const double &operator[](unsigned) const;
 
    friend std::istream &operator>>(std::istream &, Row &);
    friend std::ostream &operator<<(std::ostream &, const Row &);
 
    bool operator==(const Row &) const;
    bool operator!=(const Row &) const;
 
    const Row &operator=(const Row &);
};
 
#endif
Row.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include "Row.h"
#include <iostream>
 
// Конструктор по-умолчанию
Row::Row():
// Устанавливаем размер строки по-умолчанию
_size(1)
{
    // Выделяем память под строку
    _row = new double [_size];
 
    // Заполняем строку нулевыми значениями
    for (unsigned i = 0; i < _size; ++i)
        _row[i] = 0.0;
}
 
// Конструктор с параметрами
// size - размер строки
// fill - значение, которым изначально будет заполнена строка (по-умолчанию 0)
Row::Row(unsigned size, double fill):
// Устанавливаем размер строки
_size(size)
{
    // Выделяем память под строку
    _row = new double [_size];
 
    // Заполняем строку желаемыми значениями
    for (unsigned i = 0; i < _size; ++i)
        _row[i] = fill;
}
 
// Конструктор копирования
Row::Row(const Row &original):
// Устанавливаем размер строки
_size(original._size)
{
    // Выделяем память под строку
    _row = new double [_size];
 
    // Инициализируем элементы новой строки
    // элементами строки original
    for (unsigned i = 0; i < _size; ++i)
        _row[i] = original._row[i];
}
 
// Деструктор
Row::~Row()
{
    // Освобождаем память, отведённую под строку
    delete [] _row;
}
 
// Функция, возвращающая размер строки
unsigned Row::size() const
{
    // Возвращаем размер строки
    return _size;
}
 
// Функция изменения размера строки
void Row::resize(unsigned size, double fill)
{
    // Если исходный размер строки не
    // совпадает с желаемым
    if (_size != size)
    {
        // Устанавливаем размер строки
        // равным желаемому
        _size = size;
 
        // Освобождаем память из-под исходной строки
        delete [] _row;
 
        // Выделяем память под строку нового размера
        _row = new double [_size];
    }
 
    // Заполняем строку желаемыми значениями
    for (unsigned i = 0; i < _size; ++i)
        _row[i] = fill;
}
 
// Перегруженный оператор взятия значения по индексу
double &Row::operator[](unsigned index)
{
    // Возвращаем ссылку на желаемое значение
    return _row[index];
}
 
// Перегруженный оператор взятия значения по индексу (константный)
const double &Row::operator[](unsigned index) const
{
    // Возвращаем константную ссылку на желаемое значение
    return _row[index];
}
 
// Перегруженный оператор вывода из потока input
std::istream &operator>>(std::istream &input, Row &rhs)
{
    // Идём по элементам очередной строки
    for (unsigned i = 0; i < rhs._size; ++i)
        // Выводим значение из потока
        // input в очередной элемент
        // строки
        input >> rhs._row[i];
 
    // Возвращаем ссылку на поток input
    return input;
}
 
// Перегруженный оператор ввода в поток output
std::ostream &operator<<(std::ostream &output, const Row &rhs)
{
    // Идём по элементам очередной строки
    for (unsigned i = 0; i < rhs._size; ++i)
    {
        // Если очередной элемент
        // отрицательный - выводим
        // в поток output знак "минус"
        if (rhs._row[i] < 0.0)
            output << '-';
        // Иначе - выводим пробел
        else
            output << ' ';
 
        // Выводим модуль элемента в поток output
        output << (rhs._row[i] < 0.0 ? -rhs._row[i] : rhs._row[i]) << "\t";
    }
 
    // Возвращаем ссылку на поток output
    return output;
}
 
// Перегруженный оператор сравнения строк
bool Row::operator==(const Row &rhs) const
{
    // Если размеры строк не совпадают, то строки заведомо не равны
    if (_size != rhs._size)
        return false;
 
    // Если на какие-либо значения строк различаются,
    // то строки не равны
    for (unsigned i = 0; i < _size; ++i)
        if (_row[i] != rhs._row[i])
            return false;
 
    // Если как размеры, так и все элементы строк совпадают,
    // то строки равны
    return true;
}
 
// Перегруженный оператор неравенства строк
bool Row::operator!=(const Row &rhs) const
{
    // Используется уже реализованный оператор сравнения строк
    return !(*this == rhs);
}
 
// Перегруженный оператор присваивания одной строки другой
const Row &Row::operator=(const Row &rhs)
{
    // Проверка на самоприсваивание
    if (this != &rhs)
    {
        // Если размеры строк не совпадают
        if (_size != rhs._size)
        {
            // Очищаем память из-под старой строки
            delete [] _row;
 
            // Устанавливаем новый размер
            _size = rhs._size;
 
            // Выделяем память под новую строку
            _row = new double [_size];
        }
 
        // Заполняем новую строку элементами из
        // присваиваемой
        for (unsigned i = 0; i < _size; ++i)
            _row[i] = rhs._row[i];
    }
 
    return *this;
}
Matrix.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#ifndef MATRIX_H
#define MATRIX_H
 
#include "Row.h"
#include <iostream>
 
class Matrix
{
    template< typename T >
    friend void swap(T &, T &);
 
private:
    Row *_matrix;
    unsigned _cols;
    unsigned _rows;
 
public:
    Matrix(unsigned = 1, unsigned = 1, double = 0.0);
    Matrix(const Matrix &);
    ~Matrix();
 
    void resize(unsigned = 1, unsigned = 1, double = 0.0);
 
    double det() const;
    Matrix inverse() const;
    int rang() const;
    Matrix transpose() const;
 
    Row &operator[](unsigned);
    const Row &operator[](unsigned) const;
 
    friend std::istream &operator>>(std::istream &, Matrix &);
    friend std::ostream &operator<<(std::ostream &, const Matrix &);
 
    Matrix operator+(const Matrix &) const;
    const Matrix &operator+=(const Matrix &);
 
    Matrix operator-(const Matrix &) const;
    const Matrix &operator-=(const Matrix &);
 
    Matrix operator*(const Matrix &) const;
    const Matrix &operator*=(const Matrix &);
    friend Matrix operator*(const Matrix &, const double);
    friend const Matrix &operator*=(Matrix &, const double);
    friend Matrix operator*(const double, const Matrix &);
 
    Matrix operator/(const Matrix &) const;
    const Matrix &operator/=(const Matrix &);
    friend Matrix operator/(const Matrix &, const double);
    friend const Matrix &operator/=(Matrix &, const double);
    friend Matrix operator/(const double, const Matrix &);
 
    Matrix operator^(const int) const;
    const Matrix &operator^=(const int);
 
    bool operator==(const Matrix &) const;
    bool operator!=(const Matrix &) const;
 
    const Matrix &operator=(const Matrix &);
};
 
#endif
Matrix.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
#include "Matrix.h"
#include <iostream>
 
// Конструктор с параметрами
// rows - количество строк матрицы (по-умолчанию 1)
// cols - количество столбцов матрицы (по-умолчанию 1)
// fill - значение, которым изначально будет заполнена матрица (по-умолчанию 0)
Matrix::Matrix(unsigned rows, unsigned cols, double fill):
// устанавливаем размеры матрицы
_rows(rows),
_cols(cols)
{
    // Выделяем память под массив строк
    _matrix = new Row [_rows];
 
    // Устанавливаем необходимы размер для каждой строки
    // и заполняем матрицу желаемым значением
    for (unsigned i = 0; i < _rows; ++i)
        _matrix[i].resize(_cols, fill);
}
 
// Конструктор копирования
Matrix::Matrix(const Matrix &original):
// Устанавливаем размеры матрицы
_rows(original._rows),
_cols(original._cols)
{
    // Выделяем память под массив строк
    _matrix = new Row [_rows];
 
    // Каждую строку новой матрицы
    // инициализируем соответствующей
    // строкой матрицы original
    for (unsigned i = 0; i < _rows; ++i)
        _matrix[i] = original._matrix[i];
}
 
// Деструктор
Matrix::~Matrix()
{
    // Удаляем память, отведуннёю под массив строк
    delete [] _matrix;
}
 
// Функция изменения резмера матрицы
void Matrix::resize(unsigned rows, unsigned cols, double fill)
{
    // Если исходные размеры матрицы
    // не совпадают с желаемыми
    if (_rows != rows || _cols != cols)
    {
        // Освобождаем память из-под исходной матрицы
        delete [] _matrix;
 
        // Устанавливаем размеры матрицы
        // равными желаемому
        _rows = rows;
        _cols = cols;
 
        // Выделяем память под матрицу нового размера
        _matrix = new Row [_rows];
    }
 
    // Устанавливаем необходимы размер для каждой строки
    // и заполняем матрицу желаемым значением
    for (unsigned i = 0; i < _rows; ++i)
        _matrix[i].resize(_cols, fill);
}
 
// Функция, вычисляющая определитель матрицы
// Используется метод Гаусса-Жордана. Суть метода состоит в
// том, что если из данной матрицы получить с помощью элементарных
// преобразований верхнюю треугольную, то определитель исходной
// матрицы будет равен произведению элементов на главной диагонали
// полученной матрицы.
// Используются следующие свойства определителя:
// 1. Определитель не изменится, если к элементам одного ряда
//    прибавить элементы другого ряда, умноженные на произвольное
//    число
// 2. При перестановке двух параллельных рядов определитель
//    меняет знак
double Matrix::det() const
{
    Matrix copy(*this);        // Копия исходной матрицы
    double result = 1.0;       // Результат
    unsigned dim = copy._rows; // Размерность матрицы
    int sign = 1;              // Знак определителя
    bool key = true;           // Вспомогательная переменная - индикатор,
                               // была ли найдена строка с ненулевым элементом
                               // в k-ом столбце
 
    // Дальнейшие действия выполняются, только если
    // исходная матрица - квадратная
    if (copy._rows == copy._cols)
    {
        // Проходим по строкам матрицы (назовём их исходными)
        for (unsigned k = 0; k < dim; ++k)
        {
            // Если элемент на главной диагонали в исходной
            // строке - нуль, то ищем строку, где элемент
            // того же столбца не нулевой, и меняем строки
            // местами, а так же (исходя из свойства 2
            // определителя), меняем знак результата на
            // противоположный, или, если такую строку
            // найти не удалось - определитель равен нулю
            // и функция завершает работу
            if (copy._matrix[k][k] == 0.0)
            {
                // Изначально устанавливаем индикатор
                // в положение "Не найдено"
                key = false;
 
                // Идём по строкам, расположенным ниже исходной
                for (unsigned i = k + 1; i < dim; ++i)
                {
                    // Если нашли строку, где в том же столбце
                    // имеется не нулевой элемент
                    if (copy._matrix[i][k] != 0.0)
                    {
                        // Устанавливаем индикатор в положение "Найдено"
                        key = true;
 
                        // Меняем найденную и исходную строки местами
                        swap(copy._matrix[k], copy._matrix[i]);
 
                        // Меняем знак результата
                        sign *= -1;
 
                        break;
                    }
                }
            }
 
            // Если на каком-то этапе не нашли столбца с ненулевыми элементами
            // ниже k-ой позиции - определитель равен нулю
            if (!key)
                return 0.0;
 
            // Идём по строкам, которые расположены ниже исходной
            for (unsigned i = k + 1; i < dim; ++i)
            {
                // Запоминаем множитель - отношение элемента очередной
                // строки, расположенного под диагональным элементом
                // исходной строки, к диагональному элементу исходной
                // строки (для того, чтобы постепенно формировать
                // верхнетреугольную матрицу, ведь на каждом шаге
                // внешнего цикла по k внутри данного цикла будет
                // зануляться столбец элементов, расположенных
                // ниже диагонального)
                double multi = copy._matrix[i][k] / copy._matrix[k][k];
 
                // Отнимаем от очередной строки исходную, умноженную
                // на сохранённый ранее множитель
                for (unsigned j = 0; j < dim; ++j)
                    copy._matrix[i][j] -= multi * copy._matrix[k][j];
            }
 
            // Добавляем к результату очередное вычисленное значение
            // на главной диагонали, поскольку оно больше не изменится
            result *= copy._matrix[k][k];
        }
    }
    else
        return 0.0;
 
    // Окончательно формируем результат с учётом получившегося знака
    return sign * result;
}
 
// Функция, вычисляющая обратную матрицу
// Используется метод Гаусса-Жордана. Суть метода состоит в
// том, что если из данной матрицы получить с помощью
// элементарных преобразований единичную, а затем все те же
// преобразования применить к единичной матрице, то полученная
// на месте единичной матрица будет обратной матрицей для
// исходной.
Matrix Matrix::inverse() const
{
    Matrix E(_rows, _rows); // Единичная матрица
    Matrix copy(*this);     // Копия исходной матрицы
    unsigned dim = _rows;   // Размернойсть матрицы
    
    // Все дальнейшие действия выполняются,
    // только если определитель исходной
    // матрицы не равен нулю
    if (det() != 0.0)
    {
        // Формируем единичную матрицу из нулевой
        // добавлением единиц на главную диагональ
        for (unsigned i = 0; i < dim; ++i)
            E._matrix[i][i] = 1.0;
 
        // Проходим по строкам матрицы (назовём их исходными)
        // сверху вниз. На данном этапе происходит прямой ход
        // и исходная матрица превращается в верхнюю треугольную
        for (unsigned k = 0; k < dim; ++k)
        {
            // Если элемент на главной диагонали в исходной
            // строке - нуль, то ищем строку, где элемент
            // того же столбца не нулевой, и меняем строки
            // местами
            if (copy._matrix[k][k] == 0.0)
            {
                // Идём по строкам, расположенным ниже исходной
                for (unsigned i = k + 1; i < dim; ++i)
                {
                    // Если нашли строку, где в том же столбце
                    // имеется не нулевой элемент
                    if (copy._matrix[i][k] != 0.0)
                    {
                        // Меняем найденную и исходную строки местами
                        // как в исходной матрице, так и в единичной
                        swap(copy._matrix[k], copy._matrix[i]);
                        swap(E._matrix[k], E._matrix[i]);
 
                        break;
                    }
                }
            }
 
            // Запоминаем делитель - диагональный элемент
            double div = copy._matrix[k][k];
 
            // Все элементы исходной строки делим на диагональный
            // элемент как в исходной матрице, так и в единичной
            for (unsigned j = 0; j < dim; ++j)
            {
                copy._matrix[k][j] /= div;
                E._matrix[k][j] /= div;
            }
 
            // Идём по строкам, которые расположены ниже исходной
            for (unsigned i = k + 1; i < dim; ++i)
            {
                // Запоминаем множитель - элемент очередной строки,
                // расположенный под диагональным элементом исходной
                // строки
                double multi = copy._matrix[i][k];
 
                // Отнимаем от очередной строки исходную, умноженную
                // на сохранённый ранее множитель как в исходной,
                // так и в единичной матрице
                for (unsigned j = 0; j < dim; ++j)
                {
                    copy._matrix[i][j] -= multi * copy._matrix[k][j];
                    E._matrix[i][j] -= multi * E._matrix[k][j];
                }
            }
        }
 
        // Проходим по вернхней треугольной матрице, полученной
        // на прямом ходе, снизу вверх
        // На данном этапе происходит обратный ход, и из исходной
        // матрицы окончательно формируется единичная, а из единичной -
        // обратная
        for (unsigned k = dim - 1; k > 0; --k)
        {
            // Идём по строкам, которые расположены выше исходной
            for (unsigned i = k - 1; i + 1 > 0; --i)
            {
                // Запоминаем множитель - элемент очередной строки,
                // расположенный над диагональным элементом исходной
                // строки
                double multi = copy._matrix[i][k];
 
                // Отнимаем от очередной строки исходную, умноженную
                // на сохранённый ранее множитель как в исходной,
                // так и в единичной матрице
                for (unsigned j = 0; j < dim; ++j)
                {
                    copy._matrix[i][j] -= multi * copy._matrix[k][j];
                    E._matrix[i][j] -= multi * E._matrix[k][j];
                }
            }
        }
    }
    // Иначе, если определитель исходной матрицы
    // равен нулю, изменяем матрицу E так, чтобы
    // она имела одну строку и один столбец, т.е.
    // единственный элемент со значением 0
    else
        E.resize();
 
    // Возвращаем полученную на месте единичной
    // обратную матрицу или нуль в случае, если
    // обратной для данной матрицы не существует
    return E;
}
 
// Функция, вычисляющая ранг матрицы
// Используется метод элементарных преобразований.
// Суть метода состоит в том, что если из данной матрицы
// получить с помощью элементарных преобразований трапециевидную,
// а затем в полученной матрице посчитать количество нулевых строк
// и отнять его от общего количества строк, то в результате получим
// ранг матрицы
int Matrix::rang() const
{
    Matrix copy(*this); // Копия исходной матрицы
    int count = 0;      // Количество нулевых строк
    bool key = true;    // Вспомогательная переменная - индикатор,
                        // была ли найдена строка с ненулевым элементом
                        // в k-ом столбце. Также служит для определения
                        // того, является ли строка матрице нулевой
                        // (на заключительном этапе)
 
    // Проходим по строкам матрицы (назовём их исходными)
    // сверху вниз и приводим матрицу к трапециевидной
    for (unsigned k = 0; k < _rows; ++k)
    {
        // Если элемент на главной диагонали в исходной
        // строке - нуль, то ищем строку, где элемент
        // того же столбца не нулевой, и меняем строки
        // местами, или, если такую строку найти не удалось,
        // прерываем цикл
        if (copy._matrix[k][k] == 0.0)
        {
            // Изначально устанавливаем индикатор
            // в положение "Не найдено"
            key = false;
 
            // Идём по строкам, расположенным ниже исходной
            for (unsigned i = k + 1; i < _rows; ++i)
            {
                // Если нашли строку, где в том же столбце
                // имеется не нулевой элемент
                if (copy._matrix[i][k] != 0.0)
                {
                    // Устанавливаем индикатор в положение "Найдено"
                    key = true;
 
                    // Меняем найденную и исходную строки местами
                    swap(copy._matrix[k], copy._matrix[i]);
 
                    break;
                }
            }
        }
 
        // Если на каком-то этапе не нашли столбца с ненулевыми элементами
        // ниже k-ой позиции - прерываем цикл
        if (!key)
            break;
 
        // Идём по строкам, которые расположены ниже исходной
        for (unsigned i = k + 1; i < _rows; ++i)
        {
            // Запоминаем множитель - элемент очередной строки,
            // расположенный под диагональным элементом исходной
            // строки, делённый на диагональный элемент исходной
            // строки
            double multi = copy._matrix[i][k] / copy._matrix[k][k];
 
            // Отнимаем от очередной строки исходную, умноженную
            // на сохранённый ранее множитель
            for (unsigned j = 0; j < _cols; ++j)
                copy._matrix[i][j] -= multi * copy._matrix[k][j];
        }
    }
 
    // Считаем количество нулевых строк
    for (unsigned i = 0; i < _rows; ++i)
    {
        // Изначально ключ нулевой строки
        // устанавливаем в положение "Нулевая"
        key = false;
 
        // Если при проходе по строке встретился
        // ненулевой элемент, устанавливаем ключ
        // в положение "Не нулевая"
        for (unsigned j = 0; j < _cols; ++j)
            if (copy._matrix[i][j] != 0.0)
                key = true;
 
        // Если после прохода по строке ключ остался
        // в положении "Нулевая", увеличиваем счётчик
        // нулевых строк
        if (!key)
            count++;
    }
 
    // Возвращаем ранг матрицы - результат вычитания
    // из общего количества строк количества нулевых
    // строк, полученных после элементарных преобразований
    // исходной матрицы
    return _rows - count;
}
 
// Функция транспонирования матрицы
Matrix Matrix::transpose() const
{
    Matrix result(this->_cols, this->_rows); // Результирующая матрица, размеры которой
                                             // противоположны размерам исходной матрицы
 
    // В цикле идём по всем элементам исходной матрицы
    // и записываем их на места соответствующих элементов
    // результирующей матрицы (в результирующей матрице в
    // итоге будут элементы исходной матрицы, отражённые
    // относительно главной диагонали)
    for (unsigned i = 0; i < _rows; ++i)
        for (unsigned j = 0; j < _cols; ++j)
            result._matrix[i][j] = _matrix[j][i];
 
    // Возвращаем результат транспонирования
    return result;
}
 
// Перегруженный оператор взятия строки по индексу
Row &Matrix::operator[](unsigned index)
{
    // Возвращаем ссылку на желаемую строку
    return _matrix[index];
}
 
// Перегруженный оператор взятия строки по индексу (константный)
const Row &Matrix::operator[](unsigned index) const
{
    // Возвращаем константную ссылку на желаемую строку
    return _matrix[index];
}
 
// Перегруженный оператор вывода из потока input
std::istream &operator>>(std::istream &input, Matrix &rhs)
{
    // Идём по строкам матрицы
    for (unsigned i = 0; i < rhs._rows; ++i)
        // Вводим очередную строку матрицы
        input >> rhs._matrix[i];
 
    // Возвращаем ссылку на поток input
    return input;
}
 
// Перегруженный оператор ввода в поток output
std::ostream &operator<<(std::ostream &output, const Matrix &rhs)
{
    // Идём по строкам матрицы
    for (unsigned i = 0; i < rhs._rows; ++i)
        // Выводим очередную строку матрицы
        output << rhs._matrix[i] << std::endl;
 
    // Возвращаем ссылку на поток output
    return output;
}
 
// Перегруженный оператор сложения матриц, результат отдельно
Matrix Matrix::operator+(const Matrix &rhs) const
{
    Matrix result(*this); // Результирующая матрица, равна
                          // изначально первой матрице
 
    // Если количество строк и столбцов первой матрицы
    // совпадает с количеством соответственно строк и
    // столбцов второй матрицы
    if (_rows == rhs._rows && _cols == rhs._cols)
    {
        // Идём по строкам матрицы
        for (unsigned i = 0; i < _rows; ++i)
            // Идём по элементам очередной строки
            for (unsigned j = 0; j < _cols; ++j)
                // Прибавляем к каждому элементу результируещей
                // матрицы (который изначально совпадает с
                // соответствующим элементом первой матрицы)
                // соответствующий элемент второй матрицы
                result._matrix[i][j] += rhs._matrix[i][j];
    }
    // Если размеры левой и правой матриц не совпадают,
    // результатом операции сложения будет число 0
    else
        result.resize();
 
    // Возвращаем результирующую матрицу
    return result;
}
 
// Перегруженный оператор сложения матриц, результат в правой матрице
const Matrix &Matrix::operator+=(const Matrix &rhs)
{
    // Сохраняем в правую матрицу результат
    // сложения правой и левой матриц посредством
    // перегруженной операции сложения матриц
    *this = *this + rhs;
 
    return *this;
}
 
// Перегруженный оператор вычитания матриц, результат отдельно
Matrix Matrix::operator-(const Matrix &rhs) const
{
    // Используется уже реализованный оператор
    // умножения матрицы на число и оператор
    // сложения матриц
    return *this + (-1.0) * rhs;
}
 
// Перегруженный оператор вычитания матриц, результат в левой матрице
const Matrix &Matrix::operator-=(const Matrix &rhs)
{
    // Используется уже реализованный оператор
    // вычитания матриц
    *this = *this - rhs;
 
    return *this;
}
 
// Перегруженный оператор умножения двух матриц, результат отдельно
Matrix Matrix::operator*(const Matrix &rhs) const
{
    Matrix result(_rows, rhs._cols); // Результирующая матрица будет иметь столько же
                                     // строк, сколько и левая матрица, и столько же
                                     // столбцов, сколько правая
 
    // Умножение матриц возможно, только если
    // количество столбцов левой матрицы и
    // количество строк правой совпадают
    if (_cols == rhs._rows)
    {
        // Идём по строкам левой матрицы
        for (unsigned i = 0; i < _rows; ++i)
            // Идём по столбцам правой матрицы
            for (unsigned j = 0; j < rhs._cols; ++j)
                // Идём по столбцам левой (и по строка правой) матрицы
                for (unsigned k = 0; k < _cols; ++k)
                    // Формируем очередной элемент результирующей матрицы
                    result._matrix[i][j] += _matrix[i][k] * rhs._matrix[k][j];
    }
    // Если количество столбцов левой и количество
    // строк правой матрицы не совпадают, то
    // результатом выполнения операции будет
    // число 0
    else
        result.resize();
 
    // Возвращаем результат умножения
    return result;
}
 
// Перегруженный оператор умножения двух матриц, результат в левой матрице
const Matrix &Matrix::operator*=(const Matrix &rhs)
{
    // Используется уже реализованный оператор
    // умножения матриц
    *this = *this * rhs;
 
    return *this;
}
 
// Перегруженный оператор умножения матрицы на число
// (матрица слева, число справа), результат отдельно
Matrix operator*(const Matrix &lhs, const double rhs)
{
    Matrix result(lhs); // Изначально результирующая матрица
                        // совпадает с исходной
 
    // Каждый элемент исходной матрицы умножаем на требуемое число
    for (unsigned i = 0; i < lhs._rows; ++i)
        for (unsigned j = 0; j < lhs._cols; ++j)
            result._matrix[i][j] *= rhs;
 
    // Возвращаем результирующую матрицу
    return result;
}
 
// Перегруженный оператор умножения матрицы на число
// (матрица слева, число справа), результат в матрице
const Matrix &operator*=(Matrix &lhs, const double rhs)
{
    // Используется уже реализованный оператор
    // умножения матрицы на число
    lhs = lhs * rhs;
 
    return lhs;
}
 
// Перегруженный оператор умножения матрицы на число
// (матрица справа, число слева), результат отдельно
Matrix operator*(const double lhs, const Matrix &rhs)
{
    // Используется уже реализованный оператор
    // умножения матрицы на число
    return rhs * lhs;
}
 
// Перегруженный оператор деления матриц (т.е. умножения левой
// матрицы на обратную для правой матрицу), результат отдельно
Matrix Matrix::operator/(const Matrix &rhs) const
{
    // Используется уже реализованный оператор умножения
    // матриц, а так же функция, находящая обратную матрицу
    return *this * rhs.inverse();
}
 
// Перегруженный оператор деления матриц (т.е. умножения левой
// матрицы на обратную для правой матрицу), результат в левой матрице
const Matrix &Matrix::operator/=(const Matrix &rhs)
{
    // Используется уже реализованный оператор деления матриц
    *this = *this / rhs;
 
    return *this;
}
 
// Перегруженный оператор деления матрицы на число (т.е.
// умножение матрицы на обратное число), результат отдельно
Matrix operator/(const Matrix &lhs, const double rhs)
{
    // Используется уже реализованный оператор умножения
    // матрицы на число
    return lhs * (1.0 / rhs);
}
 
// Перегруженный оператор деления матрицы на число (т.е. умножения
// матрицы на обратное число), результат в матрице
const Matrix &operator/=(Matrix &lhs, const double rhs)
{
    // Используется уже реализованный оператор деления
    // матрицы на число
    lhs = lhs / rhs;
 
    return lhs;
}
 
// Перегруженный оператор деления числа на матрицу (т.е. умножения
// числа на обратную матрицу), результат отдельно
Matrix operator/(const double lhs, const Matrix &rhs)
{
    // Используется уже реализованный оператор умножения
    // матрицы на число, а так же функция, находящая
    // обратную матрицу
    return lhs * rhs.inverse();
}
 
// Перегруженная операция возведения матрицы в целую степень
// (положительную или отрицательную), результат отдельно
Matrix Matrix::operator^(const int power) const
{
    Matrix result(*this);                         // Изначально в результирующую матрицу копируем исходную
    unsigned _power = power > 0 ? power : -power; // Сохраняем абсолютное значение показателя степени
 
    // Продолжаем, только если матрица квадратная
    if (_rows == _cols)
    {
        // Если показатель степени равен нулю, то результирующей матрицей
        // будет являться единичная матрица той же размерности, что и исходная
        if (_power == 0)
        {
            // Заполняем результирующую матрицу нулями
            result.resize(_rows, _cols, 0.0);
 
            // Устанавливаем единицы на главной диагонали
            for (unsigned i = 0; i < _rows; ++i)
                result._matrix[i][i] = 1.0;
        }
        // Если показатель степени ненулевой
        else
        {
            // Возводим матрицу в нужную степень
            for (unsigned i = 1; i < _power; ++i)
                result *= *this;
 
            // Если исходный показатель был отрицательным,
            // обращаем полученную матрицу
            if (power < 0)
                result = result.inverse();
        }
    }
    // Если матрица неквадратная, результатом выполнения
    // операции будет число 0
    else
        result.resize();
 
    // Возвращаем результат возведения матрицы в степень
    return result;
}
 
// Перегруженная операция возведения матрицы в целую степень
// (положительную или отрицательную), результат в матрице
const Matrix &Matrix::operator^=(const int power)
{
    // Используется уже реализованный оператор возведения
    // матрицы в целую степень
    *this = *this ^ power;
 
    return *this;
}
 
// Перегруженный оператор сравнения матриц
bool Matrix::operator==(const Matrix &rhs) const
{
    // Если размеры матриц не совпадают, то матрицы заведомо не равны
    if (_rows != rhs._rows || _cols != rhs._cols)
        return false;
 
    // Если на какие-либо строки матриц различаются,
    // то матрицы не равны
    for (unsigned i = 0; i < _rows; ++i)
        if (_matrix[i] != rhs._matrix[i])
            return false;
 
    // Если как размеры, так и все элементы матриц совпадают,
    // то матрицы равны
    return true;
}
 
// Перегруженный оператор неравенства матриц
bool Matrix::operator!=(const Matrix &rhs) const
{
    // Используется уже реализованный оператор сравнения матриц
    return !(*this == rhs);
}
 
// Перегруженный оператор присваивания одной матрицы другой
const Matrix &Matrix::operator=(const Matrix &rhs)
{
    // Проверка на самоприсваивание
    if (this != &rhs)
    {
        // Если размеры матриц не совпадают
        if (_rows != rhs._rows || _cols != rhs._cols)
        {
            // Очищаем память из-под старой матрицы
            delete [] _matrix;
 
            // Устанавливаем новые размеры
            _rows = rhs._rows;
            _cols = rhs._cols;
 
            // Выделяем память под новую матрицу
            _matrix = new Row [_rows];
 
            // Устанавливаем необходимы размер для каждой строки
            for (unsigned i = 0; i < _rows; ++i)
                _matrix[i].resize(_cols);
        }
 
        // Заполняем новую матрицу элементами из
        // присваиваемой
        for (unsigned i = 0; i < _rows; ++i)
            _matrix[i] = rhs._matrix[i];
    }
 
    return *this;
}
 
// Шаблонная функция обмена двух элементов местами
template< typename T >
void swap(T &a, T &b)
{
    // Стандартный обмен переменных местами
    T temp = a;
    a = b;
    b = temp;
}
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
16.12.2010, 03:57     Класс матриц #8
Скину и свой вариант что-ли...
Писал давненько. Около пары месяцев назад, а может и больше. В универ надо было. Ну вообщем как-то так

matrix.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#ifndef _MATRIX_H_
#define _MATRIX_H_
 
namespace MatrSpace
{
    //Matrix container class
    template<class T>
    class AbstractMatr
    {
    public:
        AbstractMatr() {}
        AbstractMatr(size_t n, size_t m);
        AbstractMatr(const AbstractMatr&Ob):Matrix(Ob.Matrix) {}
        virtual ~AbstractMatr() {}
        void SetSize(size_t n, size_t m);
        inline const size_t GetRow() const {return Matrix.size();}
        inline const size_t GetCol() const {return Matrix[0].size();}
        void swap(AbstractMatr&);
    protected:
        std::vector<std::vector<T> > Matrix;
    };
 
    //Math Matr. public from AbstractMatr
    template<class T>
    class MathMatr:public AbstractMatr<T>
    {
    public:
        MathMatr():AbstractMatr() {}
        MathMatr(size_t n, size_t m):AbstractMatr<T>(n, m) {}
        MathMatr(const AbstractMatr<T>& Ob):AbstractMatr<T>(Ob) {}
        virtual ~MathMatr() {}
        const MathMatr<T>& operator =(const MathMatr&);
        const MathMatr<T>& operator +=(const MathMatr&);
        const MathMatr<T> operator +(const MathMatr&) const;
        const MathMatr<T>& operator *=(const MathMatr&);
        const MathMatr<T> operator *(const MathMatr&) const;
        virtual void input(std::istream&) {}
        virtual void output(std::ostream&) const {}
        template<class T2>
        friend std::ostream& operator <<(std::ostream&, const MathMatr<T2>& Ob);
        template<class T2>
        friend std::istream& operator >>(std::istream&, MathMatr<T2>& Ob);
        void random_fill();
    };
 
    //InOutMatr class. Public from MathMatr
    template<class T>
    class IOMatr:public MathMatr<T>
    {
    public:
        IOMatr():MathMatr<T>() {}
        IOMatr(size_t n, size_t m):MathMatr(n, m) {}
        IOMatr(const AbstractMatr<T>& Ob):MathMatr(Ob) {}
        virtual ~IOMatr() {}
        virtual void input(std::istream&)=0;
        virtual void output(std::ostream&) const=0;
    };
 
    //Console InOut public from IOMatr
    template<class T>
    class ConsoleMatr:public IOMatr<T>
    {
    public:
        ConsoleMatr():IOMatr<T>() {}
        ConsoleMatr(size_t n, size_t m):IOMatr(n, m) {}
        ConsoleMatr(const AbstractMatr<T>& Ob):IOMatr(Ob) {}
        virtual ~ConsoleMatr() {}
        const ConsoleMatr<T>& operator =(const ConsoleMatr&);
        const ConsoleMatr<T>& operator +=(const ConsoleMatr&);
        const ConsoleMatr<T> operator +(const ConsoleMatr&) const;
        const ConsoleMatr<T>& operator *=(const ConsoleMatr&);
        const ConsoleMatr<T> operator *(const ConsoleMatr&) const;
        virtual void input(std::istream&);
        virtual void output(std::ostream&) const;
    };
    
    //AbstractMatr func-members
    template<class T>
    AbstractMatr<T>::AbstractMatr(size_t n, size_t m)
    {
        Matrix.resize(n);
        for(int i=0; i!=GetRow(); ++i)
        {
            Matrix[i].resize(m);
        }
    }
 
    template<class T>
    void AbstractMatr<T>::SetSize(size_t n, size_t m)
    {
        if(GetRow()!=0&&GetCol()!=0)
            Matrix.clear();
        Matrix.resize(n);
        for(int i=0; i!=GetRow(); ++i)
        {
            Matrix[i].resize(m);
        }
    }
 
    template<class T>
    void AbstractMatr<T>::swap(AbstractMatr<T>& Ob)
    {
        Matrix.swap(Ob.Matrix);
    }
    
    //MathMatr func-membets
    template<class T>
    const MathMatr<T>& MathMatr<T>::operator =(const MathMatr<T>& Ob)
    {
        MathMatr<T> Temp(Ob);
        Temp.swap(*this);
        return *this;
    }
 
    template<class T>
    const MathMatr<T>& MathMatr<T>::operator +=(const MathMatr<T>& Ob)
    {
        if(GetRow()!=Ob.GetRow()&&GetCol()!=Ob.GetCol())
            throw std::invalid_argument("Size of two matrix for sum must be equal!");
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
           for(int j=0; j!=Ob.GetCol(); ++j)
           {
              Matrix[i][j]+=Ob.Matrix[i][j];
           }
        }
        return *this;
    }
 
    template<class T>
    const MathMatr<T> MathMatr<T>::operator +(const MathMatr<T>& Ob) const
    {
        MathMatr<T> Temp(*this);
        Temp+=Ob;
        return Temp;
    }
 
    template<class T>
    const MathMatr<T>& MathMatr<T>::operator *=(const MathMatr<T>& Ob)
    {
        if(GetCol()!=Ob.GetRow())
            throw std::invalid_argument("Num of 1-st matrix cols must be equal to num of 2-nd matrix rows");
        MathMatr Temp(GetRow(), Ob.GetCol());
        for(int i=0; i!=Temp.GetRow(); ++i)
        {
           for(int j=0; j!=Temp.GetCol(); ++j)
           {
              Temp.Matrix[i][j]=0;
              for(int k=0; k!=GetCol(); ++k)
              {
                 Temp.Matrix[i][j]+=Matrix[i][k]*Ob.Matrix[k][j];
              }
            }
        }
        *this=Temp;
        return *this;
    }
 
    template<class T>
    const MathMatr<T> MathMatr<T>::operator *(const MathMatr<T>& Ob) const
    {
        MathMatr<T> Temp(*this);
        Temp*=Ob;
        return Temp;
    }
 
    template<class T>
    void MathMatr<T>::random_fill()
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
             Matrix[i][j]=1+rand()%50;
          }
       }
    }
 
    template<class T>
    std::ostream& operator <<(std::ostream& os, const MathMatr<T>& Ob)
    {
       Ob.output(os);
       return os;
    }
 
    template<class T>
    std::istream& operator >>(std::istream& is, MathMatr<T>& Ob)
    {
       Ob.input(is);
       return is;
    }
    
    //ConsoleMatr func-members
    template<class T>
    void ConsoleMatr<T>::input(std::istream& is)
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
              std::cout<<"Enter Matrix ["<<i+1<<"]["<<j+1<<"]: ";
              is>>Matrix[i][j];
          }
       }
    }
 
    template<class T>
    void ConsoleMatr<T>::output(std::ostream& os) const
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
              os<<std::setw(5)<<Matrix[i][j]<<' ';
          }
          std::cout<<std::endl;
       }
    }
 
    template<class T>
    const ConsoleMatr<T>& ConsoleMatr<T>::operator =(const ConsoleMatr<T>& Ob)
    {
        ConsoleMatr Temp(Ob);
        Temp.swap(*this);
        return *this;
    }
 
    template<class T>
    const ConsoleMatr<T>& ConsoleMatr<T>::operator +=(const ConsoleMatr<T>& Ob)
    {
        if(GetRow()!=Ob.GetRow()&&GetCol()!=Ob.GetCol())
           throw std::invalid_argument("Size of two matrix for sum must be equal!");
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
           for(int j=0; j!=Ob.GetCol(); ++j)
           {
              Matrix[i][j]+=Ob.Matrix[i][j];
           }
        }
        return *this;
    }
 
    template<class T>
    const ConsoleMatr<T> ConsoleMatr<T>::operator +(const ConsoleMatr<T>& Ob) const
    {
        ConsoleMatr<T> Temp(*this);
        Temp+=Ob;
        return Temp;
    }
 
    template<class T>
    const ConsoleMatr<T>& ConsoleMatr<T>::operator *=(const ConsoleMatr<T>& Ob)
    {
        if(GetCol()!=Ob.GetRow())
            throw std::invalid_argument("Num of 1-st matrix cols must be equal to num of 2-nd matrix rows");
        ConsoleMatr Temp(GetRow(), Ob.GetCol());
        for(int i=0; i!=Temp.GetRow(); ++i)
        {
           for(int j=0; j!=Temp.GetCol(); ++j)
           {
              for(int k=0; k!=GetCol(); ++k)
              {
                 Temp.Matrix[i][j]+=Matrix[i][k]*Ob.Matrix[k][j];
              }
            }
        }
        *this=Temp;
        return *this;
    }
 
    template<class T>
    const ConsoleMatr<T> ConsoleMatr<T>::operator *(const ConsoleMatr<T>& Ob) const
    {
        ConsoleMatr<T> Temp(*this);
        Temp*=Ob;
        return Temp;
    }
}
#endif


matrix.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <vector>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <string>
#include <stdexcept>
 
#include "Matrix.h"
 
int main()
{ 
   using namespace MatrSpace;
   srand(static_cast<unsigned>(time(NULL)));
   ConsoleMatr<int> Ob1;
   size_t row, col;
   std::cout<<"Enter num of rows and cols for 1-st matrix: ";
   std::cin>>row>>col;
   Ob1.SetSize(row, col);
 
   int choise=0;
   std::cout<<"Enter 1 for fill matrix from keyboard\n"
      <<"Enter 2 for random fill matrix\n";
   std::cin>>choise;
   if(choise==1)
      std::cin>>Ob1;
   else if(choise==2)
      Ob1.random_fill();
   else
   {
      std::cerr<<"There is no such option\n";
      return 0;
   }
   std::cout<<std::endl;
   
   ConsoleMatr<int> Ob2;
   std::cout<<"Enter num of rows and cols for 2-nd matrix: ";
   std::cin>>row>>col;
   Ob2.SetSize(row, col);
 
   choise=0;
   std::cout<<"Enter 1 for fill matrix from keyboard\n"
      <<"Enter 2 for random fill matrix\n";
   std::cin>>choise;
   if(choise==1)
      std::cin>>Ob2;
   else if(choise==2)
      Ob2.random_fill();
   else
   {
      std::cerr<<"There is no such option\n";
      return 0;
   }
   std::cout<<std::endl;
 
   ConsoleMatr<int> Ob3;
   std::cout<<"First matrix\n\n"<< Ob1 <<'\n';
   std::cout<<"Second matrix\n\n"<< Ob2 <<'\n';
   try
   {
       Ob3=Ob1*Ob2;
   }
   catch(const std::invalid_argument&e) 
   {
      std::cout<<e.what()<<'\n';
      return 0;
   }
   std::cout<<"Multy of first matrix to second matrix\n\n";
   std::cout<<Ob3<<'\n';
   return 0;
}
Alinochka
 Аватар для Alinochka
3 / 3 / 1
Регистрация: 06.12.2009
Сообщений: 46
08.01.2011, 16:27     Класс матриц #9
А не подскажите как вот это реализовать???
Написать класс «Матрица», где поля класса (данные-члены класса) – элементы матрицы,
операции с матрицами – методы класса (функции-члены класса).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.01.2011, 16:47     Класс матриц
Еще ссылки по теме:

Класс матрица (осуществить вывод матриц в виде массива 3х3) C++
Реализовать класс матриц, СРОЧНО! C++
Класс матриц C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
lemegeton
 Аватар для lemegeton
2909 / 1338 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
08.01.2011, 16:47     Класс матриц #10
Любой вышеприведенный законченный класс под это описание попадает.
Yandex
Объявления
08.01.2011, 16:47     Класс матриц
Ответ Создать тему
Опции темы

Текущее время: 20:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru