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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.71
metaluga145
243 / 244 / 20
Регистрация: 08.04.2013
Сообщений: 927
#1

Критику в студию - C++

25.04.2013, 23:39. Просмотров 2315. Ответов 30
Метки нет (Все метки)

Доброго всем времени суток! Я вот написал такой себе класс матриц, прошу оценить его и посоветовать что можно улучшить или изменить, как повысить быстродействие или, возможно, что-то надо добавить.
Знаю,что надо сделать шаблон класса для разных типов данных, но дабы сейчас все было красиво и хорошо не загрязнял этим код! Любые дельные советы будут "лайкнуты"!

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
//класс матриц
//matrix.h
/*проверка от дураков не предусмотрена*/
#pragma once
#include <iostream>
#include <fstream>
 
class matrix
{
public:
    matrix();//конструктор по умолчанию
    matrix(const int& , const int&);//конструктор, создает еденичную матрицу
    matrix(const int& , const int& , const double *array);//конструктор, берет значения из массива
    matrix::matrix(matrix &);//конструктор копирования
    ~matrix();//деструктор
 
protected:
    double *array;//массив матрицы
    int rows, columns;//количество столбцов и строк
    int precision;//точность вывода матрицы
 
public:
//операции с матрицей
    matrix& set(const double* );//функция изминения значения всех элементов матрицы
    matrix& eye();//делает матрицу еденичной(возможно не квадратной)
    matrix& zero();//делает матрицу нулевой
    matrix  transpose();//функция траспонирования, возвращает матрицу
//операторы
    matrix  operator*(const matrix& );//оператор умножения матриц
    matrix  operator*(const double&);//оператор умножение на дабл
    matrix  operator+(const matrix& );//оператор сложения матриц
    matrix  operator-(const matrix& );//оператор вычитания матриц
    matrix& operator=(const matrix& );//оператор присваивания
    double&      operator()(const int&, const int&);//оператор получения элемента матрицы
//дополнительные функции
    void householderDecomposition(matrix& Q, matrix& R);//алгоритм Хаусхолдера, изменяет параметры-ссылки
//функции установок параметров матрицы
    void output();//вывод матрицы на экран
    void output(std::ofstream* );//вывод матрицы в файл
    void SetSize (const int&, const int&);//изменение размеров
    int& Columns (void);//вывод количества столбцов
    int& Rows (void);//вывод количества строк
    void SetPrecison (const int &);//установка точности вывода
};
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
//класс матриц
//matrix.cpp
/*проверка от дураков не предусмотрена*/
#include "StdAfx.h"
#include "matrix.h"
#include <iomanip>
#include <math.h>
 
//конструктор по умолчанию
matrix::matrix():rows(0),columns(0),precision(2)
{
    array=NULL;
}
//конструктор еденичной матрицы
matrix::matrix(const int& rows, const int& columns) :
    rows(rows), columns(columns), precision(2)
{
    array = new double[rows * columns];
    this->eye();
}
//конструктор из массива
matrix::matrix(const int& rows, const int& columns, const double *array) :
    rows(rows), columns(columns), precision(2)
{
    this->array = new double[rows * columns];
    for (int i = 0; i < rows * columns; i++) this->array[i] = array[i];
}
//конструктор копирования
matrix::matrix(matrix &copy) 
{
    rows=copy.rows;
    columns=copy.columns;
    precision=copy.precision;
    array = new double [rows*columns];
    for( int i =0; i < rows * columns; ++i)
        array[i]=copy.array[i];
}
//деструктор
matrix::~matrix() 
{
    delete [] array;
}
//ввод данных из массива
matrix& matrix::set(const double *array) 
{
    for (int i = 0; i < rows * columns; i++) this->array[i] = array[i];
    return *this;
}
//моздание единичной матрицы
matrix& matrix::eye() 
{
    for (int j = 0; j < rows; j++)
        for (int i = 0; i < columns; i++)
            array[j * columns + i] = i == j ? 1.0 : 0.0;
    return *this;
}
//создание нулевой матрицы
matrix& matrix::zero() 
{
    for (int j = 0; j < rows; j++)
        for (int i = 0; i < columns; i++)
            array[j * columns + i] = 0.0;
    return *this;
}
//транспонированная матрица 
matrix matrix::transpose() 
{
    matrix temp(columns, rows);
    for (int j = 0; j < rows; j++)
        for (int i = 0; i < columns; i++)
            temp.array[i * rows + j] = array[j * columns + i];
    return temp;
}
//оператор умножения матриц
matrix matrix::operator*(const matrix& right_arg) 
{
    matrix temp(rows, right_arg.columns);
    for (int j = 0; j < rows; j++)
        for (int i = 0; i < right_arg.columns; i++) {
            temp.array[j * right_arg.columns + i] = 0.0;
            for (int k = 0; k < columns; k++)
                temp.array[j * right_arg.columns + i] += array[j * columns + k] * right_arg.array[k * right_arg.columns + i];
        }
    return temp;
}
//оператор умножения матрицы на число
matrix matrix::operator*(const double &s) 
{
    matrix temp(rows, columns);
    for (int j = 0; j < rows; j++)
        for (int i = 0; i < columns; i++)
            temp.array[j * columns + i] = array[j * columns + i] * s;
    return temp;
}
//оператор сложения матриц
matrix matrix::operator+(const matrix& right_arg) 
{
    matrix temp(rows, columns);
    for (int j = 0; j < rows; j++)
        for (int i = 0; i < columns; i++)
            temp.array[j * columns + i] = array[j * columns + i] + right_arg.array[j * columns + i];
    return temp;
}
//оператор вычитания матриц
matrix matrix::operator-(const matrix& right_arg) 
{
    matrix temp(rows, columns);
    for (int j = 0; j < rows; j++)
        for (int i = 0; i < columns; i++)
            temp.array[j * columns + i] = array[j * columns + i] - right_arg.array[j * columns + i];
    return temp;
}
//оператор присваивания
matrix& matrix::operator=(const matrix& right_arg) 
{
    if (rows * columns != right_arg.rows * right_arg.columns) {
        delete [] array;
        array = new double[right_arg.rows * right_arg.columns];
    }
    rows = right_arg.rows;
    columns = right_arg.columns;
 
    for (int i = 0; i < rows * columns; i++) array[i] = right_arg.array[i];
    return *this;
}
//оператор возвращения элемента
double& matrix::operator()(const int& i, const int& j)
{
    return (array[i*columns+j]);
}
//преобразование Хаусхолдера
void matrix::householderDecomposition(matrix& Q, matrix& R) 
{
    double mag, alpha;
    matrix x(rows, 1), u(rows, 1);
    matrix P(rows, rows), E(rows, rows);
 
    Q = matrix(rows, rows);
    R = *this;
 
    for (int i = 0; i < columns; i++) {
        x.zero(); u.zero();
        
        mag = 0.0;
        for (int j = i; j < rows; j++) {
            x.array[j] = R.array[j * columns + i];
            mag += x.array[j] * x.array[j];
        }
        mag = sqrt(mag);
        alpha = x.array[i] > 0 ? mag : -mag;
 
        mag = 0.0;
        for (int j = i; j < rows; j++) {
            u.array[j] = j == i ? x.array[j] + alpha : x.array[j];
            mag += u.array[j] * u.array[j];
        }
        mag = sqrt(mag);
 
        for (int j = i; j < rows; j++) u.array[j] /= mag;
 
        P = E - (u * u.transpose()) * 2.0;
 
        R = P * R;
        Q = Q * P;
    }
}
//вывод матрицы на экран
void matrix::output() 
{
    for (int j = 0; j < rows; j++) {
        for (int i = 0; i < columns; i++) {
            std::cout << std::fixed << std::setprecision(precision) << 
                std::setw(16) << array[j * columns + i] << "   ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}
//вывод матрицы в файл
void matrix::output(std::ofstream* file)
{
    for (int j = 0; j < rows; j++) {
        for (int i = 0; i < columns; i++) {
            *file << std::fixed << std::setprecision(precision) << 
                std::setw(16) << array[j * columns + i] << "   ";
        }
        *file << std::endl;
    }
    *file << std::endl;
}
//изменение размеров матрицы
void matrix::SetSize (const int& rows, const int& columns)
{
    if (array!=NULL)
        delete[] array;
    array=new double[rows * columns];
    this->zero();
}
//возвращаение количества стобцов
int& matrix::Columns (void)
{
    return columns;
}
//возвращает количество строк
int& matrix::Rows (void)
{
    return rows;
}
//установка точности вывода
void matrix::SetPrecison(const int& precision)
{
    matrix::precision=precision;
}
Спасибо!
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.04.2013, 23:39     Критику в студию
Посмотрите здесь:

из Борланда в Студию - C++
уважаемые господа джуниоры и синьоры программисты. помогите мне чайнику разобраться с проблемой плиз есть проект (игра) написанная...

Как войти в Visual студию? - C++
Здравствуйте!Я те то чтобы начинающий,а ещё хуже!Начал изучать Либерти Джесс Освой С++ за 21 день,и сами знаете во всех книгах написание...

Где взять STLPort под 13 студию? - C++
Сабж. З.Ы В гугле был.

Можно услышать критику - HTML, CSS
Я верстал шапку сайта, это моя первая такая работа. http://white.net76.net/ Покритикуйте, пожалуйста

Прошу критику курсов - Java
Я начинающий, образование экономическое. Хочу пойти сюда: http://mti.edu.ru/entrance/retraining/it/dev/javawebdev Стоит?

Критику.Рекомендацию.Недочеты - Рабочая станция
Здравствуйте, вот собрал сборку. Хочу критику. Видео-Gigabite Radeon R9 280 ЖД-WD Blue 500Gb Процессор-Amd FX 8320 Кулер-Zalman...

хочу критику сайта объективную - HTML, CSS
сделал свой первый сайт и хотелось бы услышать мнение опытных: что поменять, как оптимизировать и т. д. и т. п. В общем поделитесь опытом...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kastaneda
26.04.2013, 14:38     Критику в студию
  #16

Не по теме:

Да, точно, заглянул в стандарт, к POD еще структуры, юнионы и массивы скалярных типов относятся.

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
26.04.2013, 14:51     Критику в студию #17
Цитата Сообщение от ForEveR Посмотреть сообщение
В данном случае уместнее будет сказать скалярные.
Ну, если к фундаментальным добавить указатели, то получим скалярные.
MrGluck
26.04.2013, 14:56
  #18

Не по теме:

Kastaneda, и тривиальные классы, если говорить о С++11

diagon
Higher
1928 / 1194 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
26.04.2013, 15:03     Критику в студию #19
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Tulosba Посмотреть сообщение
еще не значит, что в двумерном не будет нечто подобного
Что-то я не слышал о компайлерских оптимизациях "превращение массива указателей в одномерный массив".

Цитата Сообщение от Tulosba Посмотреть сообщение
Откуда тут следует "значительно эффективнее"?
Для доступа к элементу требуется одно разыменование, а не два, как в случае с массивом указателей. Ну, это копеечная оптимизация, это да.
А вот кеш для линейного массива работает значительно лучше. Учитывая то, что доступ к памяти - наиболее времязатратная операция, получаем значительный выигрыш.
Ну и еще векторизация и префетчинг для линейного массива делается гораздо проще, чем для массива указателей. А это тоже достаточно неслабое ускорение.
В качестве бонуса, менеджер памяти гораздо быстрее поймет, что данная матрица является одним большим объектом, а не кучкой мелких. Это благотворно повлияет на общий перформанс. Ну и еще потребуется чуть-чуть меньше памяти (не понадобится хранить массив указателей).

Итого: получаем более бережное обращение с памятью и кешем в частности, что может дать очень даже неслабое ускорение (в некоторых случаях - в десятки раз).

К тому же, не стоит забывать тезис про "преждевременную оптимизацию".
Выбор подходящего способа хранения данных (равно как и выбор алгоритма) на этапе проектирования сложно назвать преждевременной оптимизацией. Все-таки если не подумать об этом в самом начале, то оптимизация, если она понадобится (а работа с матрицами достаточно часто является "горячей точкой"), будет весьма мучительной - в данном случае, как минимум, придется перепиливать все обращения по индексам.
DiffEreD
1429 / 766 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
26.04.2013, 15:05     Критику в студию #20
metaluga145, а где в классе перегруженые операторы [][]? Это же важная штука для матрицы.
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
26.04.2013, 16:22     Критику в студию #21
yuron_477, Есть оператор (), который используется для данных действий полагаю.
metaluga145
243 / 244 / 20
Регистрация: 08.04.2013
Сообщений: 927
26.04.2013, 16:55  [ТС]     Критику в студию #22
Спасибо всем за то,что обратили внимание на эту тему! Я прочитал очень много дельных советов, а так же было очень много вопросов по поводу "почему одномерный массив", "шаблон" и зачем там функции, которые неуместны в классе.

По поводу одномерного массив, хочу сказать, что это только начальная стадия разработки проекта. Всем известно,что функция new очень дорога по времени. С помощью этого класса буду решаться СЛАУ размерностями 100 на 100,а возможно и больше. Потому оптимизируем как можем.

По поводу шаблона было все сказано еще в самом вопросе.

Функции, такие как преобразование Хаусхолдера будут вынесены в отдельный файл(возможно класс методов работы со СЛАУ) чуть позже, тоже самое касается класса вывода матрицы.

В одном из первых постов было сделано замечание, на которое я особо хочу обратить внимание
Цитата Сообщение от MrGluck Посмотреть сообщение
Возможно, он думает, что от его супер-класса будут наследоваться.
Действительно, это не "супер-класс", но я стремлюсь к чему-то стоящему, и да, от этого класса будут наследники.

Что хочу сказать по поводу использования std::vector, не нравится мне эта идея. обращение к матрице увеличивает время работы программы.

Так же было замечание,что нигде не используется проверка на размеры. Да, так оно и есть,ибо в самом начале файлов написано "/*проверка от дураков не предусмотрена*/", дабы пока что не загрязнять код.

По поводу очень полезного замечания
Цитата Сообщение от yuron_477 Посмотреть сообщение
metaluga145, а где в классе перегруженые операторы [][]? Это же важная штука для матрицы.
Если вы расскажете, как сделать перегрузку такого оператора для одномерного массива, буду очень благодарен, а пока что там есть перегрузка (), которая выполняет роль [][].

Отдельное спасибо хочу сказать Olivеr, 0x10, Kastaneda, diagon.

Еще остается вопрос, а как сделать так,чтобы в операторах +, - и тд. не надо было создавать временную переменную данного класса?
DiffEreD
1429 / 766 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
26.04.2013, 17:12     Критику в студию #23
Цитата Сообщение от metaluga145 Посмотреть сообщение
как сделать перегрузку такого оператора
при таком выделении памяти думаю что никак. Посмотри как я это делал(второй вариант кода): Небольшой шаблонный класс matrix: комментарии/критика относительно кода с точки зрения правильности написания
Там много лишнего, но общий подход, думаю, должен быть таким.
metaluga145
243 / 244 / 20
Регистрация: 08.04.2013
Сообщений: 927
26.04.2013, 17:21  [ТС]     Критику в студию #24
yuron_477, спасибо. Правда из-за шаблонов очень сложно читается)потому не хотел пока писать все в шаблонах))но спасибо)
diagon
Higher
1928 / 1194 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
26.04.2013, 17:33     Критику в студию #25
Цитата Сообщение от metaluga145 Посмотреть сообщение
[][].
Можно возвращать прокси-объект, но это геморройно нерационально. В бустоматрицах, к примеру, используют оператор () и не жалуются.

Цитата Сообщение от metaluga145 Посмотреть сообщение
Еще остается вопрос, а как сделать так,чтобы в операторах +, - и тд. не надо было создавать временную переменную данного класса?
Ну, можно принимать результирующую матрицу по ссылке (при этом переписать с оператора на метод) или пойти на другие извращения. Но это некрасиво.
В нормальных компиляторах есть rvo/nrvo/rvalue-references, гарантирующие, что лишнего копирования/конструирования не будет.
Kastaneda
26.04.2013, 17:34
  #26

Не по теме:

Цитата Сообщение от diagon Посмотреть сообщение
и префетчинг для линейного массива делается гораздо проще
Ага, я своими глазами видел как удобное для кэша испльзование памяти дает +50% к скорости. А вот префетчинг совими руками ничего не дал, точнее он дал выигрыш при отключеном хардварном префетчинге (в линуксе это можно делать), но при включеном похоже только мешал.

metaluga145
243 / 244 / 20
Регистрация: 08.04.2013
Сообщений: 927
26.04.2013, 17:39  [ТС]     Критику в студию #27
diagon, я вот только начал учиться пользоваться бустами и еще не успел заметить, что там уже есть матрицы) Спасибо,что открыли глаза на это)
Tulosba
26.04.2013, 17:48
  #28

Не по теме:

Цитата Сообщение от metaluga145 Посмотреть сообщение
Спасибо,что открыли глаза на это)
Что, теперь наследования от супер-класса не будет? :-(

metaluga145
26.04.2013, 17:50  [ТС]
  #29

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
Что, теперь наследования от супер-класса не будет? :-(
Будет. Просто теперь есть где подсмотреть вдруг что и откуда поучиться писать этот класс.

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.04.2013, 18:06     Критику в студию
Еще ссылки по теме:

С++ Builder XE 5 включить критику синтаксиса - C++ Builder
Возможно ли в С++ Builder XE 5 включить критику синтаксиса на подобии visual studio 2012?

Жду критику по поводу своей работы - Web-дизайн
Создали с товарищем сайт строительной компании. Сразу скажу, что с шапкой перестарались, будем изменять. Хотелось бы услышать Ваше...

Игровой блок 56тыщ критику пжлст - Игровой компьютер
не смог скинуть картинку, боже, как стыдно.

Пожалуйста, дайте конструктивную критику на дизайн! - Web-дизайн
Всем здравствуйте! Учусь писать сайты, но, к сожалению, у меня проблемы с дизайном. Я могу сказать нравится мне или не нравится, плохо...

Тестовое задание от работадателя. Хотелось бы услышать критику. - C++
Пробую устроиться программистом. Вот одна из компаний выслала мне тестовое задание следующего содержания: Немного поломав голову,...


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

Или воспользуйтесь поиском по форуму:
diagon
26.04.2013, 18:06     Критику в студию
  #30

Не по теме:

Цитата Сообщение от Kastaneda Посмотреть сообщение
префетчинг совими руками
Так я и не предлагал явно использовать софтварный префетчинг :)
Просто при обходе одномерного массива он должен работать эффективнее, чем при обходе массива массивов.

Yandex
Объявления
26.04.2013, 18:06     Критику в студию
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru