Матрица стл умножения цепи


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

#ifndef MATRIX_H_
#define MATRIX_H_

#include <string>

struct Matrix_error
{
    Matrix_error(std::string error)
    {
        m_error = error;
    }
    std::string m_error;
};

class Matrix
{
public:
    Matrix(std::string name, std::pair<int, int> dim, int mult);

    Matrix operator* (Matrix &m) throw (Matrix_error)
    {
        if (m_dim.second != m.m_dim.first) {
            throw Matrix_error(std::string("ERROR:" 
                "Matrix Multiplication Dimension Error")
                + m_name + m.m_name + std::string("\n"));
        }
        Matrix M(std::string("("+m_name + m.m_name+")"), 
            std::pair<int, int>(m_dim.first, m.m_dim.second), 
            m.m_mult + m_mult + m_dim.first*m_dim.second*m.m_dim.second);
        return M;
    }
    int getMultiplications() const {return m_mult;}
    std::string getName() const {return m_name;}
    std::pair<int,int> getDimensions() const {return m_dim;}
private:
    std::string m_name;
    std::pair<int,int> m_dim;
    int m_mult;

    friend std::ostream& operator<< (std::ostream &out, Matrix &m)
    {
        return out << m.m_name << "(" << m.m_dim.first
                   << ", " << m.m_dim.second << ")";
    }
};

#endif /* MATRIX_H_ */

#include <iostream>
#include <string>
#include "matrix.h"

Matrix::Matrix(std::string name, std::pair<int, int> dim, int mult = 0)
{
    m_name = name;
    m_dim = dim;
    m_mult = mult;
}

#include <iostream>
#include <list>
#include <iterator>
#include <cstdlib>
#include "matrix.h"

/*
 * Declare typedefs up front. Keep them to a minimal
 * to help readability and reduce amount of scrolling
 */
typedef std::list<Matrix>::iterator matrix_it;
typedef std::list<Matrix> matrix_chain;

/*
 * This function prints out the final results of 
 * the computations.
 */
void print_matrix_chain(matrix_it left, matrix_it right)
{
    while (left != right) {
        std::cout << (*left) << " = " << (*left).getMultiplications()  
                  << std::endl;
        left++;
    }
}

/*
 * This function finds the optimal way to multiply
 * N matrices together when provided a list of N
 * matrices
 */
matrix_chain optimal_matrix_chain_multiplication(matrix_chain &chain) 
{
    matrix_chain ret;
    if (chain.size() == 1) {
        ret.push_back(chain.front());
        chain.pop_front();
    } else if (chain.size() == 2) {
        Matrix A = chain.front();
        chain.pop_front();
        Matrix B = chain.front();
        chain.pop_front();
        Matrix C = (A*B);
        ret.push_back(A*B);
    } else {
        matrix_it pos = chain.begin();
        pos++;                                      //Start pos 1 from the left
        matrix_it end = chain.end();

        for (; pos != end; pos++) {
            matrix_chain left;
            matrix_chain right;
            copy(chain.begin(), pos, back_inserter(left));
            copy(pos, chain.end(), back_inserter(right));

            left = optimal_matrix_chain_multiplication(left);
            right = optimal_matrix_chain_multiplication(right);

            matrix_it lbegin = left.begin();
            matrix_it rbegin = right.begin();
            matrix_it lend = left.end();
            matrix_it rend = right.end();
            for (; lbegin != lend; lbegin++) {
                for(; rbegin != rend; rbegin++) {
                    try {
                        ret.push_back((*lbegin)*(*rbegin));
                    } catch (Matrix_error e) {
                        std::cout << e.m_error;
                    }
                }
            }
        }
    }
    return ret;   
}

int main(int argc, char *argv[])
{
    std::list<Matrix> chain;
    Matrix A(std::string("A"), std::pair<int, int>(5, 10), 0);
    chain.push_back(A);
    Matrix B(std::string("B"), std::pair<int, int>(10, 7), 0);
    chain.push_back(B);
    Matrix C(std::string("C"), std::pair<int, int>(7, 11), 0);
    chain.push_back(C);
    Matrix D(std::string("D"), std::pair<int, int>(11, 2), 0);
    chain.push_back(D);
    Matrix E(std::string("E"), std::pair<int, int>(2, 5), 0);
    chain.push_back(E);
    std::list<Matrix> ret = optimal_matrix_chain_multiplication(chain);

    print_matrix_chain(ret.begin(), ret.end());

    return 0;
}


2035
1
задан 8 сентября 2011 в 11:09 Источник Поделиться
Комментарии
4 ответа

Несколько слов про обработку исключений в коде - структура Matrix_error.
Рассмотрим следующий документ - ошибки и обработка исключений - для надлежащего оформления исключения классы в C++:



  1. Создайте производный класс исключений, от std::исключение. За исключением
    очень редких случаях, когда вы не можете позволить себе стоимость виртуального
    стол, std::исключение делает разумное исключение базового класса, и
    при использовании универсально, позволяет программистам поймать "все"
    не прибегая к поймать(...).

  2. Не добавьте в СТД::строка, объект или любой другой элемент данных или
    базового класса, чей конструктор копирования может бросить исключение. Что может
    ведут прямо к СТД::terminate()Для в кидать пункта. Аналогично,
    это плохая идея, чтобы использовать базу или членов рядовых которых конструктор(ы)
    может бросить, потому что, хотя и не обязательно фатальным для вашей программы

  3. Существуют различные способы, чтобы избежать копирования объектов string, когда
    исключения копируются, в том числе внедрение фиксированной длины буфера в
    объект исключения, или управляющий строк с помощью подсчета ссылок.
    Тем не менее, рассмотрим следующий момент, прежде, чем заниматься какой-либо из этих
    подходы.

  4. Формат что() сообщение по требованию, если вы чувствуете, что вам действительно необходимо
    формат сообщения. Форматирование сообщение об ошибке исключения обычно
    операция требовательные к памяти, которая потенциально может бросить
    исключение. Эту операцию лучше отложить до после стека
    раскручивание произошло, и, вероятно, выделить определенные ресурсы. Это
    хорошая идея в этом случае для защиты вашего настоящего (функции) с
    блок catch(...) так что у вас есть запасной вариант в случае форматирования
    код бросает


2
ответ дан 9 сентября 2011 в 05:09 Источник Поделиться

Андрей знает гораздо больше меня, так что к его советам об использовании std::исключение, а не делать свои собственные ошибки класса, даже если бы это было хорошо, вы передаете сообщение об ошибке в по значению, не по ссылке, которая причиняет ненужную копию.

struct Matrix_error
{
Matrix_error(std::string error)
{

// you probably would want
Matrix_error( std::string const & error)

// and since it's passed to the c'tor, you could use the member initialization list, which // is ever-so-slightly more correct

Matrix_error( std::string & error) : m_error( error ) {}

// the reason that's considered more correct is that in your code, the default c'tor is
// called first, then you are assigning it, which is a wasted call to the default c'tor. // If you supply it on the mem initialization list, then the c'tor is called directly with // the argument, so it saves a step. This can add up when initializing objects that are
// more complex than just strings.

// you might even be able to go a step futher, and declare m_error a const string, since // in principle, the error object should never need to *modify* the error message it
// takes, only print it out or log it somewhere. This is more correct because the more you
// use const, the less stuff can get changed, which means in the long run, fewer bugs and
// more correct designs.

1
ответ дан 10 сентября 2011 в 12:09 Источник Поделиться

Я не так тщательно, как корпия++, но вот некоторые вопросы кодирования.

Matrix(std::string name, std::pair<int, int> dim, int mult);

действительно должны быть

Matrix(std::string const& name, std::pair<int, int> const& dim, int const mult);

Да "int строительства мульт" является педантичным, но и явно указывает на ваши намерения, т. е. копировать только значения.

Лишних скобок ошибка меня.
<<(*слева)
должно быть

<< *left

(*left).getMultiplications()

должно быть

left->getMultiplications()

1
ответ дан 13 сентября 2011 в 01:09 Источник Поделиться

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

0
ответ дан 10 сентября 2011 в 11:09 Источник Поделиться