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

В C, если бы я хотел создать матричную структуру, я использовал бы:

struct matrix {
  int col, row;
  double data[1]; // I want the matrix entries stored
                  // right after this struct
}

Затем я могу выделить его с

matrix* allocate_matrix(int row, int col) {
  matrix* m = malloc(sizeof(matrix) + sizeof(double) * (row * col - 1));
  m->row = row; m->col = col;
  return m;
}

Теперь я делаю equiv в C++?

Править:

Я хочу знать канонический способ реализовать матричный класс в C++.

25
задан svick 25 March 2015 в 20:06
поделиться

8 ответов

load () инициирует запрос Ajax для извлечения HTML, который при возврате устанавливается в заданный селектор.

Все функции jQuery Ajax являются просто обертками для $ .ajax () так что:

$("#id").load(...);

, вероятно, эквивалентно:

$.ajax({
  url: "...",
  dataType: "html",
  success: function(data) {
    $("#id").html(data);
  }
});
-121--1236922-

Насколько я знаю, в Django ORM нет одношагового способа сделать это.

Но вы можете разделить его на два запроса:

bakeries = Bakery.objects.annotate(
    hottest_cake_baked_at=Max('cake__baked_at')
) 
hottest_cakes = Cake.objects.filter(
    baked_at__in=[b.hottest_cake_baked_at for b in bakeries]
)

Если id's тортов продвигаются вместе с bake_at отметками времени, вы можете упростить и устранить неоднозначность вышеуказанного кода (в случае, если два торта приходят одновременно, вы можете получить оба из них):

hottest_cake_ids = Bakery.objects.annotate(
    hottest_cake_id=Max('cake__id')
).values_list('hottest_cak‌​e_id', flat=True)

hottest_cakes = Cake.objects.filter(id__in=hottest_cake_ids)

Кредиты BTW за это достаются Дэниелу Розману, который однажды ответил на мой аналогичный вопрос:

http://groups.google.pl/group/django-users/browse_thread/thread/3b3cd4cbad478d34/3e4c87f336696054?hl=pl&q =

Если вышеупомянутый метод слишком медленный, то я знаю и второй метод - вы можете написать пользовательский SQL, производящий только те Торты, которые являются самыми горячими в соответствующих пекарнях, определить его как базу данных VIEW, а затем написать неуправляемую модель Джанго для него. Он также упоминается в приведенном выше потоке django-users. Прямая ссылка на оригинальную концепцию здесь:

http://web.archive.org/web/20130203180037/http ://wolfram.kriesing.de/blog/index.php/2007/django-nice-and-critical-article # comment-48425

Надеюсь, что это поможет.

-121--915337-

C++ в основном является супернабором C. Вы можете продолжать делать то, что делали.

При этом в C++ необходимо определить соответствующий класс Matrix, который управляет собственной памятью. Он может, например, поддерживаться внутренним std:: vector , и можно переопределить оператор [] или оператор () для соответствующей индексации в вектор (например, см. Как создать оператор подстрочного индекса для класса Matrix? ) из C++ FAQ.

Начните:

class Matrix
{
public:
    Matrix(size_t rows, size_t cols);
    double& operator()(size_t i, size_t j);
    double operator()(size_t i, size_t j) const;

private:
    size_t mRows;
    size_t mCols;
    std::vector<double> mData;
};

Matrix::Matrix(size_t rows, size_t cols)
: mRows(rows),
  mCols(cols),
  mData(rows * cols)
{
}

double& Matrix::operator()(size_t i, size_t j)
{
    return mData[i * mCols + j];
}

double Matrix::operator()(size_t i, size_t j) const
{
    return mData[i * mCols + j];
}

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

20
ответ дан 28 November 2019 в 18:07
поделиться

Если вы хотите иметь возможность заполнения нуля, как необязательно, так и високосных секунд:

/^((0?[1-9])|(1[0-2])):[0-5]\d:(([0-5]\d)|(60)) [AP]M$/

Пробой:
(0? [1-9] | 1 [0-2]) 1-9 (с опциональным нулем начала) или 10-12
[0-5] [0-9] 00-59 (0-5 для первой цифры, 0-9 для второй)
([0-5] [0-9]) | (60) високосные секунды
[AP] M AM/PM

-121--3783535-

Вот исходный код функции load : http://github.com/jquery/jquery/blob/master/src/ajax.js#L15

Как вы видите, это $ ajax с некоторыми функциями обработки. Другими словами, удобный способ.

-121--1236925-

Существует множество тонкостей в настройке эффективного и качественного класса матрицы. К счастью, существует несколько хороших реализаций.

Подумайте над тем, хотите ли вы класс матрицы фиксированного размера или класс переменной размера. то есть вы можете сделать это:

// These tend to be fast and allocated on the stack.
matrix<3,3> M; 

или вы должны иметь возможность сделать это

// These are slower but more flexible and partially allocated on the heap 
matrix M(3,3); 

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

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

4
ответ дан 28 November 2019 в 18:07
поделиться

Вы могут сделать это таким образом Отказ Единственное отличие заключается в том, что вам нужно будет отличить результат из Malloc .

Скорее, вы будете использовать вектор , либо в качестве 1D массива с вычисленной индексацией или встроенным вектором. (Первые соответствует вашему коду лучше.)

Например:

template <typename T> // often, they are templates
struct matrix
{
    // should probably be hidden away, and the class would
    // provide `at` and `operator()` for access
    int col, row;
    std::vector<T> data;

    matrix(int columns, int rows) :
    col(columns), row(rows), 
    data(col * row)
    {}

}

matrix m(4, 4);
m.data[1 + 1 * 4] = /* ... */;

или:

template <typename T>
struct matrix
{
    int col, row;
    std::vector<std::vector<T> > data;

    matrix(int columns, int rows) :
    col(columns), row(rows), 
    data(col, std::vector(row))
    {}
}

matrix m(4, 4);
m.data[1][1] = /* ... */;

Но это только примеры. Вы бы хотели сделать полноценный класс; Если вы хотите больше советов по этому вопросу, отредактируйте свой вопрос и уточните, вы хотите знать канонический способ реализации матричных классов.

Есть ранее существующие классы матрицы. Мой любимый состоит в том, что от Boost, UBLAS .

3
ответ дан 28 November 2019 в 18:07
поделиться

Вы можете использовать шаблон, например:

#include <iostream>
using std::cerr;
using std::endl;

//qt4type
typedef unsigned int quint32;

template <typename T>
void deletep(T &) {}
template <typename T>
void deletep(T* & ptr) {
    delete ptr;
    ptr = 0;
}
template<typename T>
class Matrix {
    public:
        typedef T value_type;
        Matrix() : _cols(0), _rows(0), _data(new T[0]), auto_delete(true) {};
        Matrix(quint32 rows, quint32 cols, bool auto_del = true);

        bool exists(quint32 row, quint32 col) const;
        T & operator()(quint32 row, quint32 col);
        T operator()(quint32 row, quint32 col) const;
        virtual ~Matrix();

        int size() const { return _rows * _cols; }
        int rows() const { return _rows; }
        int cols() const { return _cols; }
    private:
        Matrix(const Matrix &);
        quint32 _rows, _cols;
        mutable T * _data;
        const bool auto_delete;
};
template<typename T>
Matrix<T>::Matrix(quint32 rows, quint32 cols, bool auto_del) : _rows(rows), _cols(cols), auto_delete(auto_del) {
    _data = new T[rows * cols];
}
template<typename T>
inline T & Matrix<T>::operator()(quint32 row, quint32 col) {
    return _data[_cols * row + col];
}
template<typename T>
inline T Matrix<T>::operator()(quint32 row, quint32 col) const {
    return _data[_cols * row + col];
}

template<typename T>
bool Matrix<T>::exists(quint32 row, quint32 col) const {
    return (row < _rows && col < _cols);
}

template<typename T>
Matrix<T>::~Matrix() {
    if(auto_delete){
        for(int i = 0, c = size(); i < c; ++i){
            //will do nothing if T isn't a pointer
            deletep(_data[i]);
        }
    }
    delete [] _data;
}

int main() {
    Matrix< int > m(10,10);
    quint32 i = 0;
    for(int x = 0; x < 10; ++x) {
        for(int y = 0; y < 10; ++y, ++i) {
            m(x, y) = i;
        }
    }
    for(int x = 0; x < 10; ++x) {
        for(int y = 0; y < 10; ++y) {
            cerr << "@(" << x << ", " << y << ") : " << m(x,y) << endl;
        }
    }
}

* Редактировать, исправить опечатку.

3
ответ дан 28 November 2019 в 18:07
поделиться
- 3783533-

В C ++ вы можете использовать следующим образом:

matrix *p = new matrix;

после этого

delete p; 
-2
ответ дан 28 November 2019 в 18:07
поделиться

Вы можете сделать это с шаблоном, если размер матрицы известен при компиляции времени:

template <int width, int height>
class Matrix{
    double data[height][width];
    //...member functions
};
2
ответ дан 28 November 2019 в 18:07
поделиться

Для класса Matrix вы хотите держаться подальше от перегрузки оператора [] .
См. FAQ C ++ FAQ 13.10

Кроме того, поиск в Интернете для некоторых классов Matrix Freeware. Худший случай, они могут дать вам руководство. Лучший случай, меньше программного обеспечения, которое вы должны написать и отладку .

2
ответ дан 28 November 2019 в 18:07
поделиться

nota bene.

Этот ответ сейчас имеет 20 голосов, но он не предназначен для одобрения std::valarray.

По моему опыту, время лучше потратить на установку и обучение использованию полноценной математической библиотеки, такой как Eigen. Valarray обладает меньшим количеством функций, чем у конкурентов, но он не является более эффективным или особенно простым в использовании.

Если вам нужно только немного линейной алгебры, и вы не хотите ничего добавлять в вашу цепочку инструментов, тогда, возможно, подойдет valarray. Но застрять в неспособности выразить математически правильное решение вашей проблемы - это очень плохая позиция. Математика неумолима и неумолима. Используйте правильный инструмент для работы.


Стандартная библиотека предоставляет std::valarray. std::vector<>, предложенная здесь некоторыми другими, предназначена в качестве контейнера общего назначения для объектов. valarray, менее известный, поскольку более специализированный (не использующий в качестве термина С++ термин "специализированный"), имеет несколько преимуществ:

  • Он не выделяет лишнего места. Вектор вектор округляется до ближайшей силы двойки при выделении, так что вы можете изменять его размер без перераспределения каждый раз. (Вы все еще можете изменить размер валаррея Valarray; он все еще так же дорог, как realloc().)
  • Вы можете нарезать его, чтобы легко получить доступ к строкам и столбцам.
  • Арифметические операторы работают так, как Вы ожидаете.

Конечно, преимущество перед использованием C заключается в том, что Вам не нужно управлять памятью. Размеры могут находиться в стеке или в фрагменте объекта.

std::valarray<double> matrix( row * col ); // no more, no less, than a matrix
matrix[ std::slice( 2, col, row ) ] = pi; // set third column to pi
matrix[ std::slice( 3*row, row, 1 ) ] = e; // set fourth row to e
38
ответ дан 28 November 2019 в 18:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: