C ++矩阵类

时间:2010-01-16 07:58:16

标签: c++ matrix

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

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

编辑:

我想知道用C ++实现矩阵类的方法。

11 个答案:

答案 0 :(得分:35)

nota bene。

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

根据我的经验,安装和学习使用完整的数学库(例如Eigen)会花费更多时间。 Valarray的功能比竞争对手少,但效率不高或使用起来特别容易。

如果你只需要一点线性代数,并且你不想在你的工具链中添加任何内容,那么valarray可能适合。但是,被困无法表达对你的问题的数学上正确的解决方案是一个非常糟糕的位置。数学是无情和无情的。使用正确的工具完成工作。


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

  • 它没有分配额外的空间。分配时,vector向上舍入为最接近的2的幂,因此您可以在不重新分配的情况下调整大小。 (您仍然可以调整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

答案 1 :(得分:18)

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

那就是说,在C ++中,你应该做的是定义一个管理自己内存的正确的Matrix类。例如,它可以由内部std::vector支持,您可以覆盖operator[]operator()以适当地索引到向量中(例如,请参阅:How do I create a subscript operator for a Matrix class?) 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];
}

(请注意,上面没有进行任何边界检查,我将其留作练习来模板化,以便它适用于double以外的其他内容。)

答案 2 :(得分:4)

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

仔细考虑是否需要固定大小的矩阵类或可变大小的矩阵类。 你可以这样做:

// 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)。如果在紧密循环中使用,那么动态需要一些黑客可以绕过大量的小分配。

答案 3 :(得分:3)

可以这样做。唯一的区别是你需要从malloc投射结果。

相反,您可以使用vector,作为带有计算索引的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

答案 4 :(得分:3)

您可以使用以下模板:

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

*编辑,修正了错字。

答案 5 :(得分:2)

如果在编译时已知矩阵大小,则可以使用模板执行此操作:

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

答案 6 :(得分:2)

对于矩阵类,您希望远离[]运算符的重载 见C++ FAQ 13.10

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

答案 7 :(得分:0)

Github Link

//
//  iBS_Matrix.h
//
//
//  Created by nash on 11/29/15.
//  Copyright 2015 iBean Software.
//  All rights reserved.
//  current copy on Github:
//
#ifndef iBS_Matrix_h
#define iBS_Matrix_h

const int Matrix_MAJOR_VERSION = 1;
const int Matrix_MINOR_VERSION = 0;

#include <iostream>
#include <vector>
namespace iBS
{
struct Matrix 
{
    std::vector<std::vector<int> > a; 

    Matrix& operator =(Matrix& o)
    {
        a.resize(o.a.size());
        for(int i=0;i<a.size();i++)
            a[i].resize(o.a[i].size());
        for(int i=0;i<a.size();i++) 
            for(int j=0;j<a[i].size();j++) 
            {
                a[i][j] = o.a[i][j];
            }
        return *this;
    }

    Matrix& operator +(Matrix& o)
    {
        for(int i=0;i<a.size();i++) 
            for(int j=0;j<a[i].size();j++) 
            {
                a[i][j] = a[i][j] + o.a[i][j];
            }
        return *this;
    }
    Matrix& operator -(Matrix& o)
    {
        for(int i=0;i<a.size();i++) 
            for(int j=0;j<a[i].size();j++) 
            {
                a[i][j] = a[i][j] - o.a[i][j];
            }
        return *this;
    }
    Matrix& operator *(Matrix& o)
    {
        if(a[0].size() != o.a.size()) return *this;

        Matrix tm;
        tm.a.resize(a.size());
        for(int i=0;i<tm.a.size();i++)
            tm.a[i].resize(o.a[0].size());

        for(int i=0;i<tm.a.size();i++) 
            for(int j=0;j<tm.a[i].size();j++) 
            {
                tm.a[i][j] = 0;
                for (int c=0; c<a[i].size(); c++) 
                {
                    tm.a[i][j] += a[i][c] * o.a[c][j];
                }

            }
        *this = tm;
        return *this;
    }
    Matrix& operator ^(int power)
    {
        Matrix  tM2;
        tM2 = *this;

    //   not <= below \/ because first time counts as 2
        for(int i=1; i<power; ++i)
            *this = (*this) * (tM2);

        return *this;
    }

    void print()
    {
        for(int i=0;i<a.size();i++) 
        {
            for(int j=0;j<a[i].size();j++) 
            {
                std::cout << a[i][j] << ' ';
            }
            std::cout << std::endl;
        }
        std::cout << std::endl;
    }
};

}; // end of namespace iBS

#endif // iBS_Matrix_h

答案 8 :(得分:0)

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

答案 9 :(得分:0)

我写了Matrix library来支持这么多功能。

从其文档:

  

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

<强>用法

其用法类似于c ++数组。

Matrix<int> mat(2, 2);

mat[0][0] = 2;
mat[0][1] = 23;
mat[1][0] = 0;
mat[1][1] = -6;

cout << mat[1][0];

例如,获得决定因素:

cout << det(mat);

以下是documentation

答案 10 :(得分:-2)

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

matrix *p = new matrix;

之后,

delete p;