实用矩阵类(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 ...
随机推荐
- iptables禁止某个mac地址上网
iptables -I FORWARD -m mac --mac-source 60:14:B3:7D:6B:39 -j DROP 上面这条命令测试过是可行,禁止这个mac地址上网,马上禁止马上生 ...
- socket通信中select函数的使用和解释
select函数的作用: select()在SOCKET编程中还是比较重要的,可是对于初学SOCKET的人来说都不太爱用select()写程序,他们只是习惯写诸如 conncet().accept() ...
- Microsoft Speaker Recognition API
azure说话人识别API 官方文档:https://westus.dev.cognitive.microsoft.com/docs/services/563309b6778daf02acc0a508 ...
- ABAP笔记
ABAP程序开发,经常会遇到报表开发需求.使用ABAP的Report类型程序开发报表十分便利,用很少的代码就可以快速开发出一个报表.这种报表需求,抛开各种细枝末节,都可以归结为“三步走”:1.选择屏幕 ...
- sqlserver2008 查看数据库自带的索引建议
SELECT [Total Cost] = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0) , a ...
- Python基础之字符串拼接简单介绍
字符串拼接: %s表示可以传任意类型的值,%d表示只能传数字 test = "my name is %s,age %d" %("xyp",19) print(t ...
- 使用nexus3.x搭建maven私服
前言 好久之前就想搭建maven仓库了,一直拖到了现在,也就是懒得动,现在终于是要付诸行动了.网上查了不少资料,好多博客都是关于2.x的搭建,我下载的是最新版的nexus,好多教程已经不能使用,以此记 ...
- PHP原生写的生成图片缩略图类
PHP原生写的生成图片缩略图类,本文以京东商品图片为例,分别生成三种不同尺寸的图片.调用方法很简单只要传参数高度和宽度,及新图片的名称. 引入缩略图类 include_once 'ImageResiz ...
- oracle DML语句
DML语句 1. 插入数据 创建一个新表 create table new_cust as select * from customers --使用insert语句添加行 /* 确定要插入的行所在的 ...
- Android APK反编译(二)
参考:APK反编译 工具介绍 apktool 作用:资源文件获取,可以提取出图片文件和布局文件进行使用查看 dex2jar 作用:将apk反编译成java源码(classes.dex转化成jar文件) ...