实用矩阵类(Matrix)(带测试)
引言:
无意间看到国外一个网站写的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(); }
实用矩阵类(Matrix)(带测试)的更多相关文章
- [Java]编写自己的Matrix矩阵类
用java实现一个简单的矩阵类,可以实现简单的矩阵计算功能. class Matrix 1.向量点乘 public static double dot(double[] x,double[] y) 2 ...
- 实用的随机数生成类Random:测试(随机产生100个不重复的正整数)
实用的随机数生成类Random:测试(使用Random类随机生成100个不重复的正整数) 一.之前我们使用随机数用的是Math类的random()方法: tips: 产生随机数(0~9中任意整数)的方 ...
- OpenGL矩阵类(C++)
概述 创建&初始化 存取器 矩阵运算 变换函数 实例:模型视图矩阵 实例:投影矩阵 概述 OpenGL固定功能管线提供4个不同类型的矩阵(GL_MODELVIEW.GL_PROJECTION. ...
- Java日期时间实用工具类
Java日期时间实用工具类 1.Date (java.util.Date) Date(); 以当前时间构造一个Date对象 Date(long); 构造函数 ...
- OpenGL矩阵类(C++) 【转】
http://www.cnblogs.com/hefee/p/3816727.html OpenGL矩阵类(C++) 概述 创建&初始化 存取器 矩阵运算 变换函数 实例:模型视图矩阵 实例: ...
- C++实现矩阵类和向量类
C++期末作业内容,写完之后觉得过于臃肿,又重新搞了个新的.新的当作业交,旧的拿来给同学参考. [问题描述]请仿照复数类,设计一个矩阵类,设计矩阵类的构成元素 1.编写构造函数完成初始化 2.编写成员 ...
- R语言编程艺术# 矩阵(matrix)和数组(array)
矩阵(matrix)是一种特殊的向量,包含两个附加的属性:行数和列数.所以矩阵也是和向量一样,有模式(数据类型)的概念.(但反过来,向量却不能看作是只有一列或一行的矩阵. 数组(array)是R里更一 ...
- 精解Mat类(一):基本数据类型-固定大小的 矩阵类(Matx) 向量类(Vector)
一.基础数据类型 1.(基础)固定大小矩阵类 matx 说明: ① 基础矩阵是我个人增加的描述,相对于Mat矩阵类(存储图像信息的大矩阵)而言. ② 固定大小矩阵类必须在编译期间就知晓其维 ...
- Spring统一返回Json工具类,带分页信息
前言: 项目做前后端分离时,我们会经常提供Json数据给前端,如果有一个统一的Json格式返回工具类,那么将大大提高开发效率和减低沟通成本. 此Json响应工具类,支持带分页信息,支持泛型,支持Htt ...
随机推荐
- EXT.net 图标靠右排列
toolbar1.Items.Add(Button_1); toolbar1.Items.Add(Button_2); toolbar1.Items.Add(Button_3); toolbar1.I ...
- linux安装mysql8.0及开启远程访问
第一步:获取mysql8.0的yum源 进入mysql官网获取RPM包下载地址 https://dev.mysql.com/downloads/repo/yum/ 点击下载后, 右键复制链接地 ...
- php的运行模式
1.php最常见的五种运行模式. CGI 通用网关接口 FastCGI 常驻内存的CGI CLI 命令行 Web模块 Apache等Web服务器 模块的形式加载php进程 ISAPI 已经不用了
- .net 上传文件
Controller层接收文件 参数 [FromServices] IHostingEnvironment env public IActionResult UploadFile([FromS ...
- gentoo hibernate
首先修改内核: Power management and ACPI options ---> [*] Suspend to RAM and standby [*] Hibernation (ak ...
- 使用jieba库与wordcloud库第三方库进行词频统计
一.jieba库与wordcloud库的使用 1.jieba库与wordcloud库的介绍 jieba 库的分词原理是利用一个中文词库,将待分词的内容与分词词库进行比对,通过图结构和动态规划方法找到最 ...
- C#C/S框架演示 (MES系统)
之前做过一个MES系统,发一些里面的截图.如果有朋友也用这个框架.或者有兴趣可以一起学习学习.使用开发工具VS2013,数据库SqlServer2008和Oracle11C.插件dev15.2,开发模 ...
- 【译】图解Transformer
目录 从宏观上看Transformer 把张量画出来 开始编码! 从宏观上看自注意力 自注意力的细节 自注意力的矩阵计算 "多头"自注意力 用位置编码表示序列的顺序 残差 解码器 ...
- C# 异步示例代码
在 使用BackgroundWorker组件 一文中,阐述了在Winform编程中,使用BackgroundWorker组件实现异步调用,本文主要讲述利用委托实现异步. 以下描述摘抄于MSDN: 异步 ...
- spring boot 2 统一异常处理
spring mvc 针对controller层异常统一处理非常简单,使用 @RestControllerAdvice 或 @RestControllerAdvice 注解就可以轻@RestContr ...