Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/18: Рейтинг темы: голосов - 18, средняя оценка - 4.78
petruha-cccp
1

класс Matrix (СРОЧНО !!!)

21.02.2011, 19:25. Показов 3581. Ответов 1
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Люди добрые помогите пожалуйста с решением задачи, а то я в программировании плохо соображаю.
Вот условие задачи, ПОМОГИТЕ, Я БУДУ ОЧЕНЬ БЛАГОДАРЕН !!!

Создать класс Matrix, содержащий следующие элементы:
- поле «размер» Size s;
- поле «данные» int Data[s.Raw,s.Column];
- метод получения кол-ва строк int GetRaw();
- метод получения кол-ва столбцов int GetColumn();
- метод получения значения ячейки int GetValue(int i, int j)
- конструктор с параметрами Matrix(Size s, int InitialValue);
Создать класс Size, содержащий элементы:
- поле «кол-во строк» int Raw;
- поле «кол-во столбцов» int Column;
- конструктор с параметрами Size(int Raw, int Column );
В классе Matrix перегрузить оператор ++ перемножение матриц.
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.02.2011, 19:25
Ответы с готовыми решениями:

Класс Matrix: реализовать шаблонный класс для двумерных массивов
Доброго времени суток. У меня вопрос: я создал класс Array со внутренним динамическим массивом и...

Создать класс Matrix и класс Size
Всем доброго дня!!! Помогите пожалуйста с решением задачи, а то я в программировании плохо...

Класс Matrix, Перегрузка
День добрый... У нас есть класс матрица (NxM), нужно сделать перегрузку "+", со статик матрицой всё...

Реализовать класс matrix
реализовать класс matrix. класс предназначен для работы с типом данных таблица. в классе определить...

1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
21.02.2011, 20:18 2
Лучший ответ Сообщение было отмечено как решение

Решение

Писал давно и для себя, так что то, что надо сами добавите, и что не надо - сами уберёте:
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 < _cols; ++i)
        for (unsigned j = 0; j < _rows; ++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;
}
0
21.02.2011, 20:18
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.02.2011, 20:18
Помогаю со студенческими работами здесь

Создать класс Matrix
Для соответствующего класса, перегрузить арифметические операции(+,-,*,/). При перезгузке...

Создать класс matrix
разработать класс Matrix – матрица, физически представляющая собой вектор, состоящий из заданного...

Спроектировать и реализовать класс Matrix
Спроектировать и реализовать класс Matrix, предназначенный для работы с матрицами. Класс должен...

Создать параметризированный класс Matrix
Создать параметризированный класс Matrix – матрица. Класс должен содержать конструкторы,...


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru