C++数值计算——矩阵类的实现(一)

这篇具有很好参考价值的文章主要介绍了C++数值计算——矩阵类的实现(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本系列博客将利用C++实现一系列数值算法。数值算法离不开矩阵,但是C++并未自带矩阵这一对象,直接使用数组又会带来诸多不便,因此我们需要做一些预备工作————编写一个矩阵类,实现矩阵的基本功能。一般来说,读者可以直接使用Eigen库进行矩阵计算,从头开始造轮子仅仅是为了满足笔者个人的需要。

一、成员组成

回顾矩阵的定义,我们仅需三个量就可以具体描述一个矩阵:行指标,列指标,对应位置的元素。因此我们在类Matrix(下文就如此称呼了,和代码保持一致)中定义三个数据成员:行指标,列指标,一个二重指针。

        typedef unsigned int Index;
        class Matrix{
            private:
                Index Number_of_row;//行数
                Index Number_of_column;//列数
                double **p_Matrix;//二重指针构造矩阵
}

二、基本功能的分析与实现

按一般类的定义,类Matrix需要有构造函数、析构函数和拷贝函数。构造函数生成矩阵时,矩阵的每一个位置都需要被赋值,最合适的默认值莫过于0,因此在用户未指定的情况下,默认每个值为零;如果用户指定了某个值a,则将每个位置赋值a。因此,如下创建构造函数:

        Matrix( Index num_of_row, Index num_of_column){ //一般矩阵,默认为全零矩阵。
            Number_of_row = num_of_row;
            Number_of_column = num_of_column;
            p_Matrix = new double*[num_of_row];
            for( int i = 0; i < num_of_row; i++){
                p_Matrix[i] = new double[num_of_column];
            }
            for( int i = 0; i < num_of_row; i++){
                for( int j = 0; j < num_of_column; j++){
                    p_Matrix[i][j] = 0;
                }
            }
        }
        Matrix( Index num_of_row, Index num_of_column, double value){ //一般矩阵,默认为全为value
            Number_of_row = num_of_row;
            Number_of_column = num_of_column;
            p_Matrix = new double*[num_of_row];
            for( int i = 0; i < num_of_row; i++){
                p_Matrix[i] = new double[num_of_column];
            }
            for( int i = 0; i < num_of_row; i++){
                for( int j = 0; j < num_of_column; j++){
                    p_Matrix[i][j] = value;
                }
            }
        }        

对应的析构函数和拷贝函数如下:

        //析构函数
        ~Matrix(){
            for( int i = 0; i < Number_of_row; i++){
                delete[] p_Matrix[i];
            }
            delete[] p_Matrix;
        }
        //拷贝函数
        Matrix( const Matrix &Copy_Matrix){
            Number_of_row = Copy_Matrix.Number_of_row;
            Number_of_column = Copy_Matrix.Number_of_column;
            for(int i = 0; i < Number_of_row; i++){
                p_Matrix[i] = new double[Number_of_column];
            }
            for( int i = 0; i < Number_of_row; i++){
                for( int j = 0; j < Number_of_column; j++){
                    p_Matrix[i][j] = Copy_Matrix.p_Matrix[i][j];
                }
            }
        }

对于类Matrix而言,它自然必须有能显示和改变元素值的功能,我们将这个需求交给以下两个函数:

        //输出矩阵
        void Print_Matrix(){
            for( int i = 0; i < Number_of_row; i++){
                for( int j = 0; j < Number_of_column; j++){
                    cout << p_Matrix[i][j] << " ";
                }
                cout << endl;
            }            
        }
        //改变元素,或者赋值
        void Change_Value(Index m, Index n, double x){
            if( m >= Number_of_row || n >= Number_of_column){
                cout << "Invalid! The index exceeds the range!" << endl;
            }else{
                p_Matrix[m][n] = x;
            }   
        }

当然,这种赋值的方式极度不友好,我们将在未来改写这一赋值方式。此外,我们常常需要取出某一位置的某一值,我们将这一功能交给下面这个函数:

        //取出某一元素
        friend double Get_element(Matrix &A, int m, int n){
            if(m >= 0 && m < A.Number_of_row && n >= 0 && n < A.Number_of_column){
                return A.p_Matrix[m][n];                
            }
            else{
                cout<<"The index exceeds the range!"<<endl;
                return 0;
            }
        }

三、运算符的重载

考虑矩阵的基本运算:+、-、*(包含数乘与矩阵相乘)与=(赋值),我们需要重载运算符。值得注意的是,在矩阵乘法中我们采用的循环策略,这是考虑到C++从左往右扫描数组的特点,具体可以参考《Matrix Computation》。

        //重载运算符
        //重载加法
        Matrix operator+ (const Matrix &A){
            Matrix tempMatrix(A.Number_of_row, A.Number_of_column);

            if (A.Number_of_column != this->Number_of_column || A.Number_of_row != this->Number_of_row){
                cout << "Matrices are in different size!" << endl;
            }
            else{
                for(int i = 0; i < this->Number_of_row; i++){
                    for(int j = 0; j < A.Number_of_column; j++){
                        tempMatrix.p_Matrix[i][j] = this->p_Matrix[i][j] + A.p_Matrix[i][j];
                    }
                }  
            }
            return tempMatrix;
        }
        //重载赋值
        Matrix &operator=(const Matrix &A){
            if (A.Number_of_column != this->Number_of_column || A.Number_of_row != this->Number_of_row){
                for(int i = 0; i < this->Number_of_row; i++){
                    delete[] p_Matrix[i];
                }
                delete[] p_Matrix;
                p_Matrix = new double*[A.Number_of_row];
                for( int i = 0; i < A.Number_of_row; i++){
                    p_Matrix[i] = new double[A.Number_of_column]; 
                }


                this->Number_of_row = A.Number_of_row;
                this->Number_of_column = A.Number_of_column; 
                for(int i = 0; i < this->Number_of_row; i++){
                    for(int j = 0; j < this->Number_of_column; j++){
                        this->p_Matrix[i][j] = A.p_Matrix[i][j];
                    }
                }
            }
            else{
                for(int i = 0; i < this->Number_of_row; i++){
                    for(int j = 0; j < this->Number_of_column; j++){
                        this->p_Matrix[i][j] = A.p_Matrix[i][j];
                    }
                }                              
            }      
            return *this;      
        }
        //重载减法
        Matrix operator- (const Matrix &A){
            Matrix tempMatrix(A.Number_of_row, A.Number_of_column);

            if (A.Number_of_column != this->Number_of_column || A.Number_of_row != this->Number_of_row){
                cout << "Matrices are in different size!" << endl;
            }
            else{
                for(int i = 0; i < this->Number_of_row; i++){
                    for(int j = 0; j < A.Number_of_column; j++){
                        tempMatrix.p_Matrix[i][j] = this->p_Matrix[i][j] - A.p_Matrix[i][j];
                    }
                }  
            }
            return tempMatrix;
        }      
        //重载乘法
        //数乘
        Matrix operator*(double value){
            Matrix tempMatrix(this->Number_of_row, this->Number_of_column);

            for(int i = 0; i < this->Number_of_row; i++){
                for(int j = 0; j < this->Number_of_column; j++){
                    tempMatrix.p_Matrix[i][j] = value*this->p_Matrix[i][j];
                }
            }
            return tempMatrix;
        }
        friend Matrix operator*(double value, const Matrix &A){
            Matrix tempMatrix(A.Number_of_row, A.Number_of_column);

            for(int i = 0; i < A.Number_of_row; i++){
                for(int j = 0; j < A.Number_of_column; j++){
                    tempMatrix.p_Matrix[i][j] = value*A.p_Matrix[i][j];
                }
            }
            return tempMatrix;            
        }
        //矩阵相乘
        friend Matrix operator*(Matrix &A, Matrix &B){
            Matrix tempMatrix(A.Number_of_row, B.Number_of_column);    
            if(A.Number_of_column != B.Number_of_row){
                cout<<"Invalid!"<<endl;
            }
            else{
                double s;
        
                for(int i = 0; i < A.Number_of_row; i++){
                    for(int k = 0; k < A.Number_of_column; k++){
                        s=A.p_Matrix[i][k];
                        for(int j = 0; j < B.Number_of_column; j++){
                            tempMatrix.p_Matrix[i][j] += s*B.p_Matrix[k][j];
                        }
                    }
                }
            }
            return tempMatrix;
        }

到此已经实现了矩阵的一些基本功能,在接下来的博客中,我将完善其他矩阵的功能,并且逐步实现一些古老的数值代数算法。文章来源地址https://www.toymoban.com/news/detail-588185.html

到了这里,关于C++数值计算——矩阵类的实现(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C#,数值计算,矩阵的行列式(Determinant)、伴随矩阵(Adjoint)与逆矩阵(Inverse)的算法与源代码

    本文发布矩阵(Matrix)的一些初级算法。 矩阵行列式是指矩阵的全部元素构成的行列式,设A=(a)是数域P上的一个n阶矩阵,则所有A=(a)中的元素组成的行列式称为矩阵A的行列式,记为|A|或det(A)。若A,B是数域P上的两个n阶矩阵,k是P中的任一个数,则|AB|=|A||B|,|kA|=kⁿ|A|,|A*|=

    2024年02月20日
    浏览(40)
  • C#,数值计算,矩阵的乔莱斯基分解(Cholesky decomposition)算法与源代码

    安德烈·路易斯·乔尔斯基出生于法国波尔多以北的查伦特斯海域的蒙古扬。他在波尔多参加了Lycée e,并于1892年11月14日获得学士学位的第一部分,于1893年7月24日获得第二部分。1895年10月15日,乔尔斯基进入莱科尔理工学院,在当年223名入学学生中排名第88位。他在莱科尔理工

    2024年02月22日
    浏览(40)
  • c++系列之string类的常用接口函数

    💗 💗 博客:小怡同学 💗 💗 个人简介:编程小萌新 💗 💗 如果博客对大家有用的话,请点赞关注再收藏 🌞 string时表示字符串的字符类 //使用 string类包含#include 头文件 以及 using namespace std string容量相关接口 (size(),capacity(),clear(),empty) 1.size()是元素个数 //. size()与length()方

    2024年02月10日
    浏览(37)
  • [QT编程系列-33]:科学计算 - 开源数值计算库GNU Scientific Library(简称GSL)

    目录 第1章 简介 1.1 概述 1.2 主要功能 1.3 C++接口 1.4 在QT中使用GSL的步骤 第2章 GSL C++函数库 2.1 功能概述 2.2 代码示例 GNU Scientific Library(简称GSL)是一个开源数值计算库,旨在提供各种数学和科学计算的功能。它用于解决 数学、物理、工程和计算科学中的复杂问题,并提供了

    2024年02月11日
    浏览(41)
  • 【数值分析】用幂法计算矩阵的主特征值和对应的特征向量(附matlab代码)

    用幂法计算下列矩阵的按模最大特征值及对应的特征向量 k= 1 V^T= 8 6 0 m= 8 u^T= 1.0000 0.7500 0 k= 2 V^T= 9.2500 6.0000 -2.7500 m= 9.2500 u^T= 1.0000 0.6486 -0.2973 k= 3 V^T= 9.5405 5.8919 -3.5405 m= 9.5405 u^T= 1.0000 0.6176 -0.3711 k= 4 V^T= 9.5949 5.8414 -3.7309 m= 9.5949 u^T= 1.0000 0.6088 -0.3888 k= 5 V^T= 9.6041 5.8240 -3.7753 m=

    2024年02月01日
    浏览(44)
  • 奇异值分解与矩阵逆:数值实现与优化

    奇异值分解(Singular Value Decomposition, SVD)和矩阵逆(Matrix Inverse)是线性代数和数值分析领域中非常重要的概念和方法。这两者在现实生活中的应用非常广泛,例如图像处理、信号处理、数据挖掘、机器学习等领域。在这篇文章中,我们将从以下几个方面进行深入的讨论: 背景介绍

    2024年04月12日
    浏览(32)
  • Clickhouse学习系列——一条SQL完成gourp by分组与不分组数值计算

           笔者在近一两年接触了Clickhouse数据库,在项目中也进行了一些实践,但一直都没有一些技术文章的沉淀,近期打算做个系列,通过一些具体的场景将Clickhouse的用法进行沉淀和分享,供大家参考。       首先我们假设一个Clickhouse数据表: 这个表格的字段含义如注释,

    2024年02月14日
    浏览(43)
  • 【C++成长记】C++入门 | 类和对象(上) |类的作用域、类的实例化、类的对象大小的计算、类成员函数的this指针

    🐌博主主页:🐌​倔强的大蜗牛🐌​ 📚专栏分类:C++ ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、类的作用域  二、类的实例化 三、类对象模型  四、this指针 1、this指针的引出  2 this指针的特性 类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定

    2024年04月15日
    浏览(46)
  • 【C++手撕系列】——设计日期类实现日期计算器

        😎博客昵称:博客小梦 😊最喜欢的座右铭:全神贯注的上吧!!! 😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主! 😘博主小留言:哈喽! 😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不

    2024年02月13日
    浏览(42)
  • 【数值计算方法(黄明游)】解线性代数方程组的迭代法(一):向量、矩阵范数与谱半径【理论到程序】

       注意:速读可直接跳转至“4、知识点总结”及“5、计算例题”部分   当涉及到线性代数和矩阵理论时, 向量、矩阵范数以及谱半径 是非常重要的概念,下面将详细介绍这些内容: a. 定义及性质   考虑一个 n n n 维向量 x x x ,定义一个实值函数 N ( x ) N(x) N ( x ) ,

    2024年01月25日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包