C++ 矩阵类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2076624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:01:36  来源:igfitidea点击:

C++ Matrix Class

c++matrix

提问by anon

In C, if I wanted to create a matrix struct, I would use:

在 C 中,如果我想创建一个矩阵结构,我会使用:

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

Then I can allocate it with

然后我可以分配它

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;
}

Now do I do the equiv in C++?

现在我在 C++ 中做等效吗?

EDIT:

编辑:

I want to know the cannonical way to implement a matrix class in C++.

我想知道在 C++ 中实现矩阵类的规范方法。

回答by Potatoswatter

nota bene.

请注意。

This answer has 20 upvotes now, but it is not intended as an endorsement of std::valarray.

这个答案现在有 20 个赞成票,但它并不打算作为对 的认可std::valarray

In my experience, time is better spent installing and learning to use a full-fledged math library such as Eigen. Valarray has fewer features than the competition, but it isn't more efficient or particularly easier to use.

根据我的经验,最好花时间安装和学习使用成熟的数学库,例如Eigen。Valarray 的功能比竞争对手少,但它的效率并不高,也不是特别容易使用。

If you only need a little bit of linear algebra, and you are dead-set against adding anything to your toolchain, then maybe valarraywould fit. But, being stuck unable to express the mathematically correct solution to your problem is a very bad position to be in. Math is relentless and unforgiving. Use the right tool for the job.

如果您只需要一点线性代数,并且您坚决反对向工具链添加任何内容,那么也许valarray会适合。但是,陷入无法表达问题的数学正确解决方案是一个非常糟糕的境地。数学是无情和无情的。为工作使用正确的工具。



The standard library provides std::valarray<double>. std::vector<>, suggested by a few others here, is intended as a general-purpose container for objects. valarray, lesser known because it is more specialized (not using "specialized" as the C++ term), has several advantages:

标准库提供std::valarray<double>. std::vector<>由这里的其他一些人建议,旨在作为对象的通用容器。valarray,因为它更专业(不使用“专业化”作为 C++ 术语)而鲜为人知,它有几个优点:

  • It does not allocate extra space. A vectorrounds up to the nearest power of two when allocating, so you can resize it without reallocating every time. (You can still resize a valarray; it's just still as expensive as realloc().)
  • You may slice it to access rows and columns easily.
  • Arithmetic operators work as you would expect.
  • 它不分配额外的空间。vector分配时A向上舍入到最接近的 2 次幂,因此您可以调整其大小而无需每次都重新分配。(你仍然可以调整 a 的大小valarray;它仍然和 一样昂贵realloc()。)
  • 您可以将其切片以轻松访问行和列。
  • 算术运算符按您的预期工作。

Of course, the advantage over using C is that you don't need to manage memory. The dimensions can reside on the stack, or in a slice object.

当然,与使用 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

回答by jamesdlin

C++ is mostly a superset of C. You can continue doing what you were doing.

C++ 主要是 C 的超集。你可以继续做你正在做的事情。

That said, in C++, what you ought to do is to define a proper Matrix class that manages its own memory. It could, for example be backed by an internal std::vector, and you could override operator[]or operator()to index into the vector appropriately (for example, see: How do I create a subscript operator for a Matrix class?) from the C++ FAQ.

也就是说,在 C++ 中,您应该做的是定义一个适当的 Matrix 类来管理自己的内存。例如,它可以由 internal 支持std::vector,您可以覆盖operator[]operator()适当地索引到向量中(例如,请参阅C++ FAQ 中的:如何为 Matrix 类创建下标运算符?)。

To get you started:

让您开始:

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];
}

(Note that the above doesn't do any bounds-checking, and I leave it as an exercise to template it so that it works for things other than double.)

(请注意,上面没有做任何边界检查,我把它作为一个练习来模板化它,以便它适用于除double.之外的其他事情。)

回答by Michael Anderson

There's lots of subtleties in setting up an efficient and high quality matrix class. Thankfully there's several good implementations floating about.

设置高效且高质量的矩阵类有很多微妙之处。值得庆幸的是,有几个很好的实现。

Think hard about whether you want a fixed size matrix class or a variable sized one. i.e. can you do this:

仔细考虑您是想要固定大小的矩阵类还是可变大小的矩阵类。即你能做到这一点:

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

or do you need to be able to do this

或者你需要能够做到这一点

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

There's good libraries that support either style, and some that support both. They have different allocation patterns and different performances.

有很好的库支持这两种风格,也有一些支持这两种风格。它们具有不同的分配模式和不同的性能。

If you want to code it yourself, then the template version requires some knowledge of templates (duh). And the dynamic one needs some hacks to get around lots of small allocations if used inside tight loops.

如果你想自己编码,那么模板版本需要一些模板知识(废话)。如果在紧密循环中使用,动态分配需要一些技巧来解决许多小分配。

回答by GManNickG

You coulddo it that way. The only difference is you'd need to cast the result from malloc.

可以那样做。唯一的区别是您需要将结果从malloc.

Rather, you would use a vector, either as a 1D array with computed indexing or an embedded vector. (The former matches your code better.)

相反,您可以使用vector, 作为具有计算索引的一维数组或嵌入向量。(前者更符合您的代码。)

For example:

例如:

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] = /* ... */;

Or:

或者:

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] = /* ... */;

But these are only examples. You'd want to make a full-fledged class; if you want more advice on that, edit your question and clarify you'd like to know the canonical way of implementing matrix classes.

但这些只是例子。你想要制作一个成熟的课程;如果您需要更多建议,请编辑您的问题并澄清您想知道实现矩阵类的规范方法。

There are pre-existing matrix classes. My favorite is that from boost, UBLAS.

有预先存在的矩阵类。我最喜欢的是来自 boost、UBLAS 的

回答by OneOfOne

You could use a template like :

您可以使用如下模板:

#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;
        }
    }
}

*edit, fixed a typo.

*编辑,修正了一个错字。

回答by Thomas Matthews

For a matrix class, you want to stay away from overloading the []operator.
See C++ FAQ 13.10

对于矩阵类,您希望避免重载[]运算符。
参见C++ 常见问题 13.10

Also, search the web for some freeware Matrix classes. Worst case, they can give you guidance. Best case, less software that you have to write and debug.

另外,在网上搜索一些免费软件 Matrix 类。最坏的情况,他们可以给你指导。最好的情况是,您必须编写和调试的软件更少。

回答by J.Colmsee

you could do it with a template, if the matrix size is known at compile-time :

如果在编译时已知矩阵大小,您可以使用模板来完成:

template <int width, int height>
class Matrix{
    double data[height][width];
    //...member functions
};

回答by Amir Fo

I have written a Matrix librarythat supports so many features.

我写了一个支持这么多功能的矩阵库

From its documentation:

从它的文档:

This library supports mathematics operators like multiplication, determinant, minor, cofactor and etc.

该库支持乘法、行列式、次要、辅因子等数学运算符。

Usage

用法

its usage is similar to c++ arrays.

它的用法类似于 c++ 数组。

Matrix<int> A(1, 2);
Matrix<int> B(2, 3);
Matrix<int> result(1, 3);

A[0][0] = 7;
A[0][1] = 10;

B[0][0] = 1;
B[0][1] = 4;
B[0][2] = 2;
B[1][0] = 1;
B[1][1] = 2;
B[1][2] = 100;

result = A * B;

result.dump.matrix();

Result:

结果:

Matrix view:
-            -
| 17 48 1014 |
-            -

Here is the documentationand Github repo.

这是文档Github repo

回答by ivan.ukr

There is no "canonical" way to do the matrix in C++, STL does not provide classes like "matrix". However there are some 3rd party libraries that do. You are encouraged to use them or write your own implementation.

在 C++ 中没有“规范”的方法来做矩阵,STL 不提供像“矩阵”这样的类。但是有一些 3rd 方库可以做到。鼓励您使用它们或编写自己的实现。

回答by fairstar

In C++ you can use like this:

在 C++ 中,您可以像这样使用:

matrix *p = new matrix;

After that,

在那之后,

delete p;