m0_72524251 2022-07-05 23:40 采纳率: 77.8%
浏览 39
已结题

矩阵运算,如何才能正确的得到结果

问题遇到的现象和发生背景

矩阵相加运行出来是错的

问题相关代码,请勿粘贴截图

#include
#include
#include //vector函数所包含的库
#include //调用reverse函数所包含的库
#include
using namespace std;
#include
using namespace std;
class matrix
{
public:
int r, c; //r表示行,c表示列
double** mem;
matrix(int a, int b) :r(a), c(b)
{
mem = new double* [a]; //堆区开辟一段内存 程序结束后需要手动释放
for (int i = 0; i < a; i++)
{
mem[i] = new double[b];
}
};
matrix(const matrix& p) //拷贝构造函数
{
r = p.r;
c = p.c;
mem = new double* [r]; //深拷贝,在堆区重新开辟一段内存,避免析构函数释放内存时重复释放同一块内存时而出错
for (int i = 0; i < r; i++)
{
mem[i] = new double[c];
}
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++) {
mem[i][j] = p.mem[i][j];
}
}
~matrix() //析构函数,释放在堆区开辟的内存
{
for (int i = 0; i < r; i++) {
delete[]mem[i];
}
delete[]mem;
};

//+运算符重载   也可以用全局函数来重载   matrix  operatior+(const matrix& m1,const matrix& m2)
matrix operator+ (const matrix& m)
{
    if (r != m.r || c != m.c)   //判断是否为同型矩阵
    {
        cout << "请输入正确的类型的矩阵。";
        matrix tmp(r, c);         //调用构造函数
        tmp.mem = NULL;           //将该二维指针置空,避免出现野指针的情况
        return tmp;
    }
    else {
        matrix tmp(r, c);
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++)
                tmp.mem[i][j] = mem[i][j] + m.mem[i][j];
        return tmp;
    }
}
matrix operator- (const matrix& m)
{
    if (r != m.r || c != m.c)//判断是否符合相减的条件
    {
        cout << "请输入正确的类型的矩阵。";
        matrix tmp(r, c);
        tmp.mem = NULL;
        return tmp;
    }
    else {
        matrix tmp(r, c);
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++)
                tmp.mem[i][j] = mem[i][j] - m.mem[i][j];
        return tmp;
    }
}
matrix operator* (const matrix& m)//矩阵乘
{
    if (c != m.r) {
        cout << "请输入正确的类型的矩阵。";
        matrix tmp(r, c);
        tmp.mem = NULL;
        return tmp;
    }
    else {
        matrix tmp(r, m.c);
        for (int i = 0; i < r; i++)
            for (int j = 0; j < m.c; j++)
                tmp.mem[i][j] = 0;//初始化二维数组
        for (int i = 0; i < tmp.r; i++)
            for (int j = 0; j < tmp.c; j++)
                for (int k = 0; k < c; k++)
                    tmp.mem[i][j] += (mem[i][k] * m.mem[k][j]);
        return tmp;
    }
}

//求逆运算
matrix operator/(const matrix& m)
{
    double ret = getA(m);
    /*matrix inverse(m.r, m.c);
    for (int i = 0; i < r; i++)
        for (int j = 0; j < m.c; j++)
            inverse.mem[i][j] = 0;*/
    matrix inverse = getAStart(m);
    if (m.r != m.c || ret == 0)
    {
        cout << "请输入正确的类型的矩阵。";
        matrix tmp(r, c);
        tmp.mem = NULL;
        return tmp;
    }
    else
    {
        matrix tmp(m.r, m.c);
        for (int i = 0; i < r; i++)
            for (int j = 0; j < m.c; j++)
                tmp.mem[i][j] = 0;//初始化二维数组
        for (int i = 0; i < tmp.r; i++)
            for (int j = 0; j < tmp.c; j++)
                tmp.mem[i][j] = inverse.mem[i][j] / ret;
        return tmp;

    }
}


//按第一行展开计算|A|
double getA(const matrix& m)
{

    if (m.r == 1 && m.c == 1)
    {
        return mem[0][0];
    }
    double ans = 0;
    matrix tmp(r, m.c);
    for (int i = 0; i < r; i++)
        for (int j = 0; j < m.c; j++)
            tmp.mem[i][j] = 0;//初始化二维数组
    int i, j, k;
    for (i = 0; i < m.r; i++)
    {
        for (j = 0; j < m.r - 1; j++)
        {
            for (k = 0; k < m.r - 1; k++)
            {
                tmp.mem[j][k] = mem[j + 1][(k >= i) ? k + 1 : k];

            }
        }
        double t = getA(tmp);
        if (i % 2 == 0)
        {
            ans += tmp.mem[0][i] * t;
        }
        else
        {
            ans -= tmp.mem[0][i] * t;
        }
    }
    return ans;
}

//计算每一行每一列的每个元素所对应的余子式,组成A*
matrix  getAStart(const matrix& m)
{
    if (m.r == 1 && m.c == 1)
    {
        matrix tmp(r, c);
        tmp.mem[0][0] = 1;
        return tmp;
    }
    matrix tmp(r, m.c);
    for (int i = 0; i < r; i++)
        for (int j = 0; j < m.c; j++)
            tmp.mem[i][j] = 0;//初始化二维数组
    int i, j, k, t;
    for (i = 0; i < m.r; i++)
    {
        for (j = 0; j < m.r; j++)
        {
            for (k = 0; k < m.r; k++)
            {
                for (t = 0; t < m.r; t++)
                {
                    tmp.mem[k][t] = mem[k >= i ? k + 1 : k][t >= j ? t + 1 : t];
                }
            }
            tmp.mem[j][i] = getA(tmp);
            if ((i + j) % 2 == 1)
            {
                mem[j][i] = -mem[j][i];
            }
        }
        return *this;
    }
}
matrix& operator=(const matrix& m)
{
    if (c != m.r) {
        cout << "请输入正确的类型的矩阵。";
        matrix tmp(r, c);
        tmp.mem = NULL;
        return tmp;
    }
    else {
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++)
                mem[i][j] = m.mem[i][j];
        return *this;
    }
}
void print(const matrix& m)//输出矩阵
{
    for (int i = 0; i < m.r; i++) {
        for (int j = 0; j < m.c; j++) {
            cout << m.mem[i][j] << ' ';
        }
        cout << endl;
    }
    cout << endl;
}

};

void matrixRead(matrix& m1, matrix& m2)
{
ofstream ofs;
ofs.open("matrix1.txt", ios::out);
ofs << 3 << " " << 3 << endl;
ofs << 1 << " " << 2 << " " << 3 << endl;
ofs << 2 << " " << 4 << " " << 5 << endl;
ofs << 3 << " " << 5 << " " << 7 << endl;
ofs << 3 << " " << 3 << endl;
ofs << 2 << " " << 4 << " " << 6 << endl;
ofs << 3 << " " << 7 << " " << 9 << endl;
ofs << 1 << " " << 5 << " " << 7 << endl;
ofs.close();

double** mem1, ** mem2;
ifstream is;
is.open("matrix1.txt", ios::in);
if (!is.is_open())
{
    cout << "文件打开失败" << endl;
    return;
}
//读取文件的行和列
int r, c;
is >> r >> c;
mem1 = new double* [r];
for (int i = 0; i < r; i++)
    mem1[i] = new double[c];
//开始读取
for (int i = 0; i < r; i++)
{
    for (int j = 0; j < c; j++)
    {
        is >> mem1[i][j];
    }
}
is >> r >> c;
mem2 = new double* [r];
for (int i = 0; i < r; i++)
    mem2[i] = new double[c];
//开始读取
for (int i = 0; i < r; i++)
{
    for (int j = 0; j < c; j++)
    {
        is >> mem2[i][j];
    }
}
is.close();

}

int main()
{
char oper;
cout << "请输入" << endl;
cin >> oper;
matrix mem1(3, 3), mem2(3, 3);
matrixRead(mem1, mem2);
matrix p3 = mem1 + mem2;
p3.print(p3);

return 0;

}

运行结果及报错内容

img

我的解答思路和尝试过的方法
我想要达到的结果

能正确的运行矩阵运算,包括加减乘以及逆运算

  • 写回答

3条回答 默认 最新

  • 关注

    matrixRead函数中,没有给m1和m2赋值。
    另外,你的matrix类中,没有无参构造函数,如果你在main函数中,直接把矩阵的行数和列数写死了,会导致内存泄漏。需要添加一个无参构造函数。
    修改后运行结果:

    img

    代码修改如下:

    #include <iostream>
    #include <fstream>
    using namespace std;
    
    class matrix
    {
    public:
        int r, c; //r表示行,c表示列
        double** mem;
    
        //这里添加2个无参构造函数
        matrix() { r = 0, c = 0, mem = 0; }
        matrix(int a, int b, double* p)
        {
            r = a;
            c = b;
            mem = new double* [a]; //堆区开辟一段内存 程序结束后需要手动释放
            for (int i = 0; i < a; i++)
            {
                mem[i] = new double[b];
                for (int j = 0; j < b; j++)
                    mem[i][j] = p[i * b + j];
            }
        }
    
        matrix(int a, int b) :r(a), c(b)
        {
            mem = new double* [a]; //堆区开辟一段内存 程序结束后需要手动释放
            for (int i = 0; i < a; i++)
            {
                mem[i] = new double[b];
            }
        };
        matrix(const matrix& p) //拷贝构造函数
        {
            r = p.r;
            c = p.c;
            mem = new double* [r]; //深拷贝,在堆区重新开辟一段内存,避免析构函数释放内存时重复释放同一块内存时而出错
            for (int i = 0; i < r; i++)
            {
                mem[i] = new double[c];
            }
            for (int i = 0; i < r; i++)
                for (int j = 0; j < c; j++) {
                    mem[i][j] = p.mem[i][j];
                }
        }
        ~matrix() //析构函数,释放在堆区开辟的内存
        {
            for (int i = 0; i < r; i++) {
                delete[]mem[i];
            }
            delete[]mem;
        };
    
        //+运算符重载   也可以用全局函数来重载   matrix  operatior+(const matrix& m1,const matrix& m2)
        matrix operator+ (const matrix& m)
        {
            if (r != m.r || c != m.c)   //判断是否为同型矩阵
            {
                cout << "请输入正确的类型的矩阵。";
                matrix tmp(r, c);         //调用构造函数
                tmp.mem = NULL;           //将该二维指针置空,避免出现野指针的情况
                return tmp;
            }
            else {
                matrix tmp(r, c);
                for (int i = 0; i < r; i++)
                    for (int j = 0; j < c; j++)
                        tmp.mem[i][j] = mem[i][j] + m.mem[i][j];
                return tmp;
            }
        }
        matrix operator- (const matrix& m)
        {
            if (r != m.r || c != m.c)//判断是否符合相减的条件
            {
                cout << "请输入正确的类型的矩阵。";
                matrix tmp(r, c);
                tmp.mem = NULL;
                return tmp;
            }
            else {
                matrix tmp(r, c);
                for (int i = 0; i < r; i++)
                    for (int j = 0; j < c; j++)
                        tmp.mem[i][j] = mem[i][j] - m.mem[i][j];
                return tmp;
            }
        }
        matrix operator* (const matrix& m)//矩阵乘
        {
            if (c != m.r) {
                cout << "请输入正确的类型的矩阵。";
                matrix tmp(r, c);
                tmp.mem = NULL;
                return tmp;
            }
            else {
                matrix tmp(r, m.c);
                for (int i = 0; i < r; i++)
                    for (int j = 0; j < m.c; j++)
                        tmp.mem[i][j] = 0;//初始化二维数组
                for (int i = 0; i < tmp.r; i++)
                    for (int j = 0; j < tmp.c; j++)
                        for (int k = 0; k < c; k++)
                            tmp.mem[i][j] += (mem[i][k] * m.mem[k][j]);
                return tmp;
            }
        }
    
       
    
    
        //求逆运算
        //matrix operator/(const matrix& m)
        matrix matrixinvers()
        {
            //double ret = getA(m);
    
            if (r != c /* || ret == 0*/)
            {
                cout << "请输入正确的类型的矩阵。";
                matrix tmp(r, c);
                tmp.mem = NULL;
                return tmp;
            }
            else
            {
                double* p = new double[r * c];
                int k = 0;
                for (int i = 0; i < r; i++)
                {
                    for (int j = 0; j < c; j++)
                        p[k++] = mem[i][j];
                }
                inverse(r, p);
                matrix tmp(r, c, p);
                return tmp;
            }
        }
    
        double det(int n, double* aa)
        {
            if (n == 1)
                return aa[0];
            double* bb = new double[(n - 1) * (n - 1)];//创建n-1阶的代数余子式阵bb    
            int mov = 0;//判断行是否移动   
            double sum = 0.0;//sum为行列式的值  
            for (int arow = 0; arow < n; arow++) // a的行数把矩阵a(nn)赋值到b(n-1)  
            {
                for (int brow = 0; brow < n - 1; brow++)//把aa阵第一列各元素的代数余子式存到bb  
                {
                    mov = arow > brow ? 0 : 1; //bb中小于arow的行,同行赋值,等于的错过,大于的加一  
                    for (int j = 0; j < n - 1; j++)  //从aa的第二列赋值到第n列  
                    {
                        bb[brow * (n - 1) + j] = aa[(brow + mov) * n + j + 1];
                    }
                }
                int flag = (arow % 2 == 0 ? 1 : -1);//因为列数为0,所以行数是偶数时候,代数余子式为1.  
                sum += flag * aa[arow * n] * det(n - 1, bb);//aa第一列各元素与其代数余子式积的和即为行列式
            }
            delete[] bb;
            return sum;
        }
    
    
    
        void inverse(int n, double* aa)
        {
            double det_aa = det(n, aa);
            //cout << "输入矩阵的行列式:" << det_aa << endl;
            if (det_aa == 0)
            {
                cout << "行列式为0 ,不能计算逆矩阵。" << endl;
                return;
            }
    
    
            double* adjoint = new double[n * n];
            double* bb = new double[(n - 1) * (n - 1)];//创建n-1阶的代数余子式阵bb   
    
            int pi, pj, q;
            for (int ai = 0; ai < n; ai++) // a的行数把矩阵a(nn)赋值到b(n-1)  
            {
                for (int aj = 0; aj < n; aj++)
                {
                    for (int bi = 0; bi < n - 1; bi++)//把元素aa[ai][0]代数余子式存到bb[][]  
                    {
                        for (int bj = 0; bj < n - 1; bj++)//把元素aa[ai][0]代数余子式存到bb[][]  
                        {
                            if (ai > bi)    //ai行的代数余子式是:小于ai的行,aa与bb阵,同行赋值  
                                pi = 0;
                            else
                                pi = 1;     //大于等于ai的行,取aa阵的ai+1行赋值给阵bb的bi行  
                            if (aj > bj)    //ai行的代数余子式是:小于ai的行,aa与bb阵,同行赋值  
                                pj = 0;
                            else
                                pj = 1;     //大于等于ai的行,取aa阵的ai+1行赋值给阵bb的bi行  
    
                            bb[bi * (n - 1) + bj] = aa[(bi + pi) * n + bj + pj];
                        }
                    }
                    /*printf("aa[%d][%d]的余子式\n", ai, aj);
                    for (int i = 0; i < n - 1; i++)
                    {
                        for (int j = 0; j < n - 1; j++)
                        {
                            printf("%lf     ", bb[i * (n - 1) + j]);
                        }
                        printf(" \n");
                    }*/
                    if ((ai + aj) % 2 == 0)  q = 1;//因为列数为0,所以行数是偶数时候,代数余子式为-1.  
                    else  q = (-1);
                    adjoint[ai * n + aj] = q * det(n - 1, bb);
                }
            }
            for (int i = 0; i < n; i++)//adjoint 转置
            {
                for (int j = 0; j < i; j++)
                {
                    int tem = adjoint[i * n + j];
                    adjoint[i * n + j] = adjoint[j * n + i];
                    adjoint[j * n + i] = tem;
                }
            }
            /*printf("伴随阵: \n");
            for (int i = 0; i < n; i++) //打印伴随阵
            {
                for (int j = 0; j < n; j++)
                {
                    cout << adjoint[i * n + j] << "\t";
                }
                cout << endl;
            }
            printf("逆矩阵: \n");*/
            for (int i = 0; i < n; i++) //打印逆矩阵
            {
                for (int j = 0; j < n; j++)
                {
                    aa[i * n + j] = adjoint[i * n + j] / det_aa;
                    //cout << aa[i * n + j] << "\t";
                }
                //cout << endl;
            }
            delete[] adjoint;
            delete[] bb;
        }
    
        matrix& operator=(const matrix& m)
        {
            
            if (this->mem != 0)
            {
                for (int i = 0; i < r; i++)
                    delete[] this->mem[i];
                delete[] this->mem;
            }
            r = m.r;
            c = m.c;
    
            this->mem = new double* [r]; //深拷贝,在堆区重新开辟一段内存,避免析构函数释放内存时重复释放同一块内存时而出错
            for (int i = 0; i < r; i++)
            {
                mem[i] = new double[c];
            }
            for (int i = 0; i < r; i++)
                for (int j = 0; j < c; j++) {
                    mem[i][j] = m.mem[i][j];
                }
            return *this;
        }
        void print()//输出矩阵
        {
            for (int i = 0; i < r; i++) {
                for (int j = 0; j < c; j++) {
                    cout << mem[i][j] << ' ';
                }
                cout << endl;
            }
            cout << endl;
        }
    };
    
    void file()
    {
        ofstream ofs;
        ofs.open("matrix1.txt", ios::out);
        ofs << 3 << " " << 3 << endl;
        ofs << 1 << " " << 2 << " " << 3 << endl;
        ofs << 2 << " " << 4 << " " << 5 << endl;
        ofs << 3 << " " << 5 << " " << 7 << endl;
        ofs << 3 << " " << 3 << endl;
        ofs << 2 << " " << 4 << " " << 6 << endl;
        ofs << 3 << " " << 7 << " " << 9 << endl;
        ofs << 1 << " " << 5 << " " << 7 << endl;
        ofs.close();
    }
    void matrixRead(matrix& m1, matrix& m2)
    {
        double** mem1, ** mem2;
        ifstream is;
        is.open("matrix1.txt", ios::in);
        if (!is.is_open())
        {
            cout << "文件打开失败" << endl;
            return;
        }
        //读取文件的行和列
        int r, c;
        is >> r >> c;
        mem1 = new double* [r];
        for (int i = 0; i < r; i++)
            mem1[i] = new double[c];
        //开始读取
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
            {
                is >> mem1[i][j];
            }
        }
    
        //给m1赋值
        m1.r = r;
        m1.c = c;
        m1.mem = mem1;
    
    
    
        is >> r >> c;
        mem2 = new double* [r];
        for (int i = 0; i < r; i++)
            mem2[i] = new double[c];
        //开始读取
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
            {
                is >> mem2[i][j];
            }
        }
    
        //给m2赋值
        m2.r = r;
        m2.c = c;
        m2.mem = mem2;
    
        is.close();
    }
    void test01()
    {
        char oper;
        cout << "请输入符号(+,-,*,/):" << endl;
        cin >> oper;
        matrix mem1, mem2, result;
        file();
        matrixRead(mem1, mem2);
        mem1.print();
        mem2.print();
    
        switch (oper)
        {
        case'+':
            result = mem1 + mem2;
            break;
        case'-':
            result = mem1 - mem2;
            break;
        case'*':
            result = mem1 * mem2;
            break;
        case'/':
            result = mem1.matrixinvers();
            break;
        default:
            cout << "请输入正确的运算符。" << endl;
        }
        result.print();
    }
    
    int main()
    {
        test01();
        return 0;
    }
    
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 7月15日
  • 已采纳回答 7月7日
  • 创建了问题 7月5日

悬赏问题

  • ¥18 深度学习tensorflow1,ssdv1,coco数据集训练一个模型
  • ¥100 关于注册表摄像头和麦克风的问题
  • ¥30 代码本地运行正常,但是TOMCAT部署时闪退
  • ¥15 关于#python#的问题
  • ¥15 主机可以ping通路由器但是连不上网怎么办
  • ¥15 数据库一张以时间排好序的表中,找出多次相邻的那些行
  • ¥50 关于DynamoRIO处理多线程程序时候的问题
  • ¥15 kubeadm部署k8s出错
  • ¥15 Abaqus打不开cae文件怎么办?
  • ¥15 小程序准备上线,软件开发公司需要提供哪些资料给甲方