实用矩阵类(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 ...
随机推荐
- WordPress版微信小程序3.0版发布
距离WordPress版微信小程序上一个版本的发布过去了一个月了.在此间,我的工作有些变化,加上正在开发新版本,目前开源版的完善和升级稍稍有些滞后. 虽然这个版本是3.0版,期间有个过渡的2.8版,不 ...
- 微信小程序web-view的简单思考和实践
微信小程序的组件web-view推出有一段时间了,这个组件的推出可以说是微信小程序开发的一个重要事件,让微信小程序不会只束缚在微信圈子里了,打开了一个口子,这个口子或许还比较小,但未来有无限可能. 简 ...
- 在Spring Boot中使用 @ConfigurationProperties 注解
但 Spring Boot 提供了另一种方式 ,能够根据类型校验和管理application中的bean. 这里会介绍如何使用@ConfigurationProperties.继续使用mail做例子. ...
- python-封装方法用于读取excel
1.实现获取excel某张表的行数.单元格数据 #coding=utf-8 import xlrd #获取excel文件 data = xlrd.open_workbook('file_path/xx ...
- react-native shadow失效
做边框阴影,但是有时候会失效,内容产生阴影,而边框无效,今天发现了原因,没错,就是没有设置背景颜色导致的.如图
- Hexo+Github博客最简教程-Dockerfile自动搭建
闲谈 拿出你的气质,打开你的电脑,借你半小时搭建好属于你的hexo博客,小生用dockerfile自动帮你搭建好:你只需要在你的mac或linux或windows上提前把docker安装好,如何安装不 ...
- es6 和 python 语法比较
http://www.linchaoqun.com/html/cms/content.jsp?id=1509528630774 Python3笔记:Python与ECMAScript部分语法对比 ht ...
- oracle 的tnsnames.ora,listener.ora
x:\app\Administrator\product\11.2.0\dbhome_1\NETWORK\ADMIN listener.ora: # listener.ora Network Conf ...
- Navicat 连接MariaDB 失败: Host '*' is not allowed to connect to this MariaDB server
题描述:Navicat 为管理方便,连接Linux 中Mariadb失败,如下如下错误:Host '*' is not allowed to connect to this MariaDB serve ...
- DOM编程艺术章12:一个简单的Ajax例子
大概入了JavaScript的门,现在要回过头恶补Ajax和json了,随手翻到dom编程艺术发现有一个适合回忆的例子,先抄录下来,引入对Ajax作用的大概印象,再去掰开了研究. <!DOCTY ...