实用矩阵类(Matrix)(带测试)

时间:2021-07-27 21:33:24

引言:

无意间看到国外一个网站写的Matrix类,实现了加减乘除基本运算以及各自的const版本等等,功能还算比较完善,,于是记录下来,以备后用:

 #ifndef MATRIX_H
#define MATRIX_H #include <iostream>
#include <functional>
#include <algorithm> using namespace std; template <size_t Rows,size_t Cols,typename ElemType = double>
class Matrix
{
public:
Matrix(); //默认构造函数
template<typename InputIterator>
Matrix(InputIterator begin, InputIterator end); //用2迭代器构造
~Matrix(); //析构函数 ElemType & at(size_t row, size_t col); //获取某个元素(引用)
const ElemType & at(size_t row, size_t col) const; size_t numRows() const; //获得行数、列数
size_t numCols() const;
size_t size() const; //返回总元素数 //多维矩阵
class MutableReference;
class ImmutableReference;
MutableReference operator[] (size_t row);
ImmutableReference operator[] (size_t row) const; typedef ElemType* iterator; //将元素类型指针定义为迭代器
typedef const ElemType* const_iterator; iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const; iterator row_begin(size_t row);
iterator row_end(size_t row);
const_iterator row_begin(size_t row) const;
const_iterator row_end(size_t row) const; Matrix& operator+= (const Matrix& rhs);
Matrix& operator-= (const Matrix& rhs);
Matrix& operator*= (const ElemType& scalar);
Matrix& operator/= (const ElemType& scalar); //打印矩阵
void printMatrix(void) const;
private:
ElemType elems[Rows*Cols]; //矩阵元素的数组 };
//两矩阵相加
template <size_t M,size_t N,typename T>
const Matrix<M, N, T> operator+ (const Matrix<M, N, T> &lhs, const Matrix<M, N, T> &rhs);
//两矩阵相减
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator- (const Matrix<M, N, T> &lhs, const Matrix<M, N, T> &rhs);
//矩阵数乘(右乘)
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator* (const Matrix<M, N, T> &lhs, const T& scalar);
//矩阵数乘(左乘)
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator* (const T& scalar, const Matrix<M, N, T> &rhs);
//矩阵除以一个数
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator/ (const Matrix<M, N, T>& lhs,const T& scalar);
//一元运算的加减 相当于添加符号
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator+ (const Matrix<M, N, T>& operand);
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator- (const Matrix<M, N, T>& operand);
//2矩阵相乘
template <size_t M, size_t N, size_t P, typename T>
const Matrix<M, P, T> operator*(const Matrix<M, N, T>& lhs,const Matrix<N, P, T>& rhs);
//矩阵的比较操作
template <size_t M, size_t N, typename T>
bool operator== (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator!= (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator< (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator<= (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator>= (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator> (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs);
//是否为单位矩阵
template <size_t M, typename T>
Matrix<M, M, T> Identity();
//矩阵转置
template <size_t M, size_t N, typename T>
const Matrix<N, M, T> Transpose(const Matrix<M, N, T>& m); //////////////////////////////////////////////////////////////////////////
/************************************************************************/
/*
函数的实现部分
*/
/************************************************************************/
//默认构造函数
template <size_t M, size_t N, typename T>
Matrix<M, N, T>::Matrix()
{
}
//迭代器构造函数
template <size_t M, size_t N, typename T>
template <typename InputIterator>
Matrix<M, N, T>::Matrix(InputIterator rangeBegin, InputIterator rangeEnd)
{
std::copy(rangeBegin, rangeEnd, begin());
}
//析构函数
template <size_t M, size_t N, typename T>
Matrix<M, N, T>::~Matrix()
{
}
//得到row,col处元素(引用) 常量版本
template <size_t M, size_t N, typename T>
const T& Matrix<M, N, T>::at(size_t row, size_t col) const
{
return *(begin() + row * numCols() + col);
}
//得到row,col处元素(引用) 非常量版本
template <size_t M, size_t N, typename T>
T& Matrix<M, N, T>::at(size_t row, size_t col)
{
return const_cast<T&>(static_cast<const Matrix<M, N, T>*>(this)->at(row, col));
}
//得到行数
template<size_t M,size_t N,typename T>
size_t Matrix<M, N, T>::numRows() const
{
return M;
}
template<size_t M,size_t N,typename T>
size_t Matrix<M, N, T>::numCols() const
{
return N;
} template<size_t M,size_t N,typename T>
size_t Matrix<M,N,T>::size() const
{
return M*N;
}
//迭代器返回首地址指针 //注意返回是迭代器类型
template<size_t M,size_t N,typename T>
typename Matrix<M, N, T>::iterator Matrix<M,N,T>::begin()
{
return elems;
}
//迭代器返回首地址指针的常量版本
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::const_iterator Matrix<M, N, T>::begin() const
{
return elems;
}
//尾迭代器获取
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::iterator Matrix<M, N, T>::end()
{
return begin()+size();
}
//尾迭代器获取(常量版本)
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::const_iterator Matrix<M, N, T>::end() const
{
return begin() + size();
}
//行迭代器(跳过指定元素获取)
template<size_t M,size_t N,typename T>
typename Matrix<M, N, T>::iterator Matrix<M, N, T>::row_begin(size_t row)
{
return begin() + row*numCols();
}
//行迭代器(跳过指定元素获取) 常量版本
template <size_t M, size_t N, typename T>
typename Matrix<M, N, T>::const_iterator Matrix<M, N, T>::row_begin(size_t row) const
{
return begin() + row*numCols();
}
//获得行尾迭代器
template<size_t M,size_t N,typename T>
typename Matrix<M, N, T>::iterator Matrix<M, N, T>::row_end(size_t row)
{
return row_begin(row) + N;
}
//获得行尾迭代器 const版本
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::const_iterator Matrix<M, N, T>::row_end(size_t row) const
{
return row_begin(row) + N;
}
/************************************************************************/
/*
方括号[]操作返回引用的实现(非const版本)
*/
/************************************************************************/
template <size_t M,size_t N,typename T>
class Matrix<M, N, T>::MutableReference
{
public:
T& operator[] (size_t col)
{
return parent->at(row, col);
}
private:
//私有构造函数 是获得此类实例的为例方法(有元类Matrix可以访问)
MutableReference(Matrix* owner, size_t row) :parent(owner), row(row)
{ }
friend class Matrix;
const size_t row;
Matrix *const parent;
};
/************************************************************************/
/*
方括号[]操作返回引用的实现(const版本)
*/
/************************************************************************/
template <size_t M, size_t N, typename T>
class Matrix<M, N, T>::ImmutableReference
{
public:
const T& operator[] (size_t col) const
{
return parent->at(row, col);
}
private:
//私有构造函数 是获得此类实例的为例方法(有元类Matrix可以访问)
ImmutableReference(const Matrix* owner, size_t row) :parent(owner), row(row)
{ }
friend class Matrix;
const size_t row;
const Matrix *const parent;
};
//方括号返回引用的真真实现(用了上面的类)
template<size_t M,size_t N,typename T>
typename Matrix<M, N, T>::MutableReference Matrix<M, N, T>::operator [] (size_t row)
{
return MutableReference(this, row);
}
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::ImmutableReference Matrix<M, N, T>::operator [] (size_t row) const
{
return ImmutableReference(this, row);
}
/************************************************************************/
/*
复合运算符实现
*/
/************************************************************************/
template <size_t M, size_t N, typename T>
Matrix<M, N, T>& Matrix<M, N, T>::operator+= (const Matrix<M, N, T>& rhs)
{
std::transform(begin(), end(), // First input range is lhs
rhs.begin(), // Start of second input range is rhs
begin(), // Overwrite lhs
std::plus<T>()); // Using addition
return *this;
} template <size_t M, size_t N, typename T>
Matrix<M, N, T>& Matrix<M, N, T>::operator-= (const Matrix<M, N, T>& rhs)
{
std::transform(begin(), end(), // First input range is lhs
rhs.begin(), // Start of second input range is rhs
begin(), // Overwrite lhs
std::minus<T>()); // Using subtraction
return *this;
}
template <size_t M, size_t N, typename T>
Matrix<M, N, T>& Matrix<M, N, T>::operator*= (const T& scalar)
{
std::transform(begin(), end(), // Input range is lhs
begin(), // Output overwrites lhs
std::bind2nd(std::multiplies<T>(), scalar)); // Scalar mult.
return *this;
}
template <size_t M, size_t N, typename T>
Matrix<M, N, T>& Matrix<M, N, T>::operator/= (const T& scalar)
{
std::transform(begin(), end(), // Input range is lhs
begin(), // Output overwrites lhs
std::bind2nd(std::divides<T>(), scalar)); // Divide by scalar
return *this;
}
/************************************************************************/
/*
双目运算符实现
*/
/************************************************************************/
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator+ (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
return Matrix<M, N, T>(lhs) += rhs; //用到了复合运算符(成员函数)
}
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator- (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
return Matrix<M, N, T>(lhs) -= rhs;
}
template <size_t M, size_t N, typename T> //(右乘一个数)
const Matrix<M, N, T> operator* (const Matrix<M, N, T>& lhs,const T& scalar)
{
return Matrix<M, N, T>(lhs) *= scalar;
}
template <size_t M, size_t N, typename T> //左乘一个数
const Matrix<M, N, T> operator* (const T& scalar,const Matrix<M, N, T>& rhs)
{
return Matrix<M, N, T>(rhs) *= scalar;
}
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator/ (const Matrix<M, N, T>& lhs,const T& scalar)
{
return Matrix<M, N, T>(lhs) /= scalar;
}
//一元运算符+
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator+ (const Matrix<M, N, T>& operand) {
return operand;
}
//一元运算符-
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator- (const Matrix<M, N, T>& operand)
{
return Matrix<M, N, T>(operand) *= T(-);
}
//2矩阵相乘
template <size_t M, size_t N, size_t P, typename T>
const Matrix<M, P, T> operator*(const Matrix<M, N, T>& one,const Matrix<N, P, T>& two)
{
/* Create a result matrix of the right size and initialize it to zero. */
Matrix<M, P, T> result;
std::fill(result.begin(), result.end(), T()); //初始化结果变量 /* Now go fill it in. */
for (size_t row = ; row < result.numRows(); ++row)
for (size_t col = ; col < result.numCols(); ++col)
for (size_t i = ; i < N; ++i)
result[row][col] += one[row][i] * two[i][col]; return result;
}
//matrix1*=matrix运算实现
template <size_t M, typename T>
Matrix<M, M, T>& operator*= (Matrix<M, M, T>& lhs,const Matrix<M, M, T>& rhs)
{
return lhs = lhs * rhs; // Nothing fancy here.
}
//比较运算符实现
template <size_t M, size_t N, typename T>
bool operator== (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
template <size_t M, size_t N, typename T>
bool operator!= (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
return !(lhs == rhs); //用了==运算符
}
/* The less-than operator uses the std::mismatch algorithm to chase down
* the first element that differs in the two matrices, then returns whether
* the lhs element is less than the rhs element. This is essentially a
* lexicographical comparison optimized on the assumption that the two
* sequences have the same size.
*/
//小于运算符
template <size_t M, size_t N, typename T>
bool operator< (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
/* Compute the mismatch. */
std::pair<typename Matrix<M, N, T>::const_iterator,
typename Matrix<M, N, T>::const_iterator> disagreement =
std::mismatch(lhs.begin(), lhs.end(), rhs.begin()); /* lhs < rhs only if there is a mismatch and the lhs's element is
* lower than the rhs's element.
*/
return disagreement.first != lhs.end() &&
*disagreement.first < *disagreement.second;
} /* The remaining relational operators are implemented in terms of <. */
template <size_t M, size_t N, typename T>
bool operator<= (const Matrix<M, N, T>& lhs, const Matrix<M, N, T>& rhs)
{
/* x <= y iff !(x > y) iff !(y < x) */
return !(rhs < lhs);
}
template <size_t M, size_t N, typename T>
bool operator>= (const Matrix<M, N, T>& lhs, const Matrix<M, N, T>& rhs)
{
/* x >= y iff !(y > x) iff !(x < y) */
return !(lhs < rhs);
}
template <size_t M, size_t N, typename T>
bool operator>(const Matrix<M, N, T>& lhs, const Matrix<M, N, T>& rhs)
{
/* x > y iff y < x */
return !(rhs < lhs);
} /* Transposition is reasonably straightforward. */ //转置
template <size_t M, size_t N, typename T>
const Matrix<N, M, T> Transpose(const Matrix<M, N, T>& m)
{
Matrix<N, M, T> result;
for (size_t row = ; row < m.numRows(); ++row)
for (size_t col = ; col < m.numCols(); ++col)
result[col][row] = m[row][col];
return result;
} /* Identity matrix just fills in the diagonal. */
template <size_t M, typename T> Matrix<M, M, T> Identity()
{
Matrix<M, M, T> result;
for (size_t row = ; row < result.numRows(); ++row)
for (size_t col = ; col < result.numCols(); ++col)
result[row][col] = (row == col ? T() : T());
return result;
}
template <size_t M,size_t N,typename T>
void Matrix<M, N, T>::printMatrix(void) const
{
for (size_t i = ; i < this->numRows();++i)
{
for (size_t j = ; j < this->numCols();++j)
{
cout << this->at(i, j)<<" ";
}
cout << endl;
}
} #endif

测试代码:

原站上并没有测试代码,为了验证类的正确性,自己写了一个简单的测试代码,仅供参考:

 #include <iostream>
#include <vector>
#include "matrix.h" using namespace std; void testMatrixClass(); int main()
{
testMatrixClass(); return ;
}
void testMatrixClass()
{
vector<int> vec1,vec2;
for (int i = ; i < ;++i)
{
vec1.push_back(i);
}
for (int i = ; i < ; ++i)
{
vec2.push_back(i+);
}
vector<int>::iterator itBegin = vec1.begin();
vector<int>::iterator itEnd = vec1.end(); Matrix<, , int>m_matrix1(itBegin,itEnd ); //用迭代器构造矩阵对象
Matrix<, , int>m_matrix2(vec2.begin(),vec2.end());
cout << "---------Matrix 1 = :-----------------" << endl;
m_matrix1.printMatrix();
cout << "---------Matrix 2 = :-----------------" << endl;
m_matrix2.printMatrix();
cout << "-----matrix1(1,1) (从0开始)= " << m_matrix1.at(, ) << endl;
cout << "---matrix1's size = " << m_matrix1.size() << " rows = " << m_matrix1.numRows()
<< " cols = " << m_matrix1.numCols() << endl;
cout << "----matrix1 *3 = " << endl;
(m_matrix1 *= ).printMatrix();
cout << "----matrix1 * matrix 2 = " << endl;
Matrix<, , int> result;
result = m_matrix1*m_matrix2;
result.printMatrix(); }