【问题标题】:Matrix Multiplication issues矩阵乘法问题
【发布时间】:2015-08-20 01:51:11
【问题描述】:

我已经实现了一个矩阵类。它为任意大小的矩阵动态分配内存。使用我的矩阵乘法函数时,它仅在特定条件下有效。如果您有两个 N*M 矩阵,则第一个矩阵的 M 必须等于第二个矩阵的 N。 示例:

//matrix constructor 'matrix M(n, m)
matrix A(2, 3), matrix B(3, 4);
//A and B can be multiplied because A_m == B_n
A * B; //this works!
//changing the size of n of the first matrix causes this to fail if n > m 
matrix C(4, 3), matrix D(3, 5);
C * D; // program becomes unresponsive for unknown reasons, only happens when C_n > C_m

我的矩阵类和乘法函数。

#include <iostream> 
class matrix{
    private:
        int rows, cols;
    public:
        int ** data;
        int row();
        int col();
        matrix();
        matrix(int, int);
        //~matrix();
        matrix operator*(matrix M);
        matrix operator%(matrix M);
        friend std::ostream & operator<<(std::ostream & os, matrix M);      
};

功能:

#include "matrix.h"

using std::cout;
using std::endl;

matrix::matrix(int r, int c){
    rows = r;
    cols = c;
    data = new int*[rows];
    for (int i = 0; i< rows; i++){
        data[i] = new int[cols];
    }
    for (int i = 0; i < rows; i++){
        for (int j = 0; j < cols; j++){
            data[i][j] = 0;
        }
    }
}

matrix::row(){
    return rows;
}

matrix::col(){
    return cols;
}

matrix matrix::operator*(matrix M){
    if (this->col() == M.row()){
        matrix result(this->row(), M.col());
        int var = 0;
        for (int i = 0; i < result.row(); i++){
            for (int j = 0; j < result.col(); j++){
                for (int k = 0; k < result.row(); k++){
                    var += this->data[i][k] * M.data[k][j];
                } 
            result.data[i][j] = var;
            var = 0;
            }
        }
        return result;
    }
    else cout << "FAILED";
} 

std::ostream & operator<<(std::ostream & os, matrix M){
    for (int i = 0; i < M.row(); i++){
        os << '|';
        for (int j = 0; j < M.col(); j++){
            os << M.data[i][j] << ' ';
        }
        os << "|\n";
    }
    os << '\n';
    return os;
}

为什么程序在这些情况下不工作?

【问题讨论】:

  • 好消息是,您在此代码中没有 rule of three 问题,因为您正在实现 none 的析构函数、copy-ctor 或 copy-赋值运算符。坏消息是,原因它不是问题是因为它像筛子一样泄漏。

标签: c++ matrix multiplication


【解决方案1】:

首先,道具

using std::cout;
using std::endl;

很高兴看到有人没有为像这样的简单工作而投入所有标准。

现在让我们来看看算法。

矩阵 C(4, 3) * 矩阵 D(3, 5) 将给出矩阵结果 (4,5)

for (int i = 0; i < result.row(); i++){
    for (int j = 0; j < result.col(); j++){
        for (int k = 0; k < result.row(); k++){

解析为

for (int i = 0; i < 4; i++){
    for (int j = 0; j < 5; j++){
        for (int k = 0; k < 4; k++){
            var += this->data[i][k] * M.data[k][j];
Array size:                   4  3           3  5

k 将运行 0 .. 3. k 的有效范围是 0 .. 2.

你想要的是:

for (int i = 0; i < result.row(); i++){
    for (int j = 0; j < result.col(); j++){
        for (int k = 0; k < this->cols; k++){

三个建议:

学习使用调试器。如果您单步执行代码,这类问题完全是微不足道的。

然后学习使用可测试的输入进行测试,这样您就可以看到数学何时不起作用。将 0 乘以 0 绝对不会证明任何事情。

我建议更换

int ** data;

std::vector<std::vector<int> > data;

你可以像这样在构造函数中初始化它:

matrix::matrix(int r, int c):rows(r), cols(c), data(r, std::vector<int>(c))
{
}

无需循环将其归零。矢量构造函数为您完成。如果不想加载零,可以指定另一个值。

matrix::matrix(int r, int c):
    rows(r), 
    cols(c), 
    data(r, std::vector<int>(c, <starting value goes here>))
{
}

【讨论】:

  • 另外,使用std::vector&lt;&gt; 方法使类默认符合三规则。 ,0 不是必需的,但这太琐碎了,几乎不值得一提。此外,虽然它不影响此代码,但应注意该成员列表中初始化程序的顺序是 not 从左到右。 rows,然后是cols,然后是data将是每个类decl中成员的顺序的初始化顺序。
  • 是的,那个 0 几乎没用。我将进行编辑以明确您可能希望在此处指定一个值的原因。和软糖。我确实弄错了顺序。我在看 row 和 col 函数。
  • 这太棒了。清楚地解决问题并提供解决方案。谢谢。
【解决方案2】:

这 3 个循环正在从分配给您的代码的块中访问内存。

for (int i = 0; i < result.row(); i++){
            for (int j = 0; j < result.col(); j++){
                for (int k = 0; k < result.row(); k++){

应该是

for (int i = 0; i < result.row(); i++){
        for (int j = 0; j < M.col(); j++){
            for (int k = 0; k < M.row(); k++){
                var += this->data[i][k] * M.data[k][j];
            }
            result.data[i][j] = var;
            var = 0;
        }
    }

【讨论】:

  • 想一想将 1x1 矩阵与 1x1 矩阵相乘时会发生什么
  • 我不认为 OP 正在查看他的函数的输出。
  • @user4581301 我对此也有严重的保留意见。如果使用此处提出的解决方案,无论操作数如何,我建议的示例将根本不产生任何乘法和一个单一值为零的 1x1 矩阵。这显然是正确的。
  • 我现在看到这行不通,总是将底行设置为 0
【解决方案3】:

我希望这段代码能正常工作。

#include<iostream>
    using namespace std;

    template<typename T>
    class Matrix{

        int rs, cs;
        T **mat;
    public:
        Matrix() { mat = NULL; rs = cs = 0; }
        istream& operator>>( Matrix <T> &);
        ofstream& operator<<(const Matrix<T> &);
        Matrix<T> operator=(const Matrix<T> &);
        Matrix<T> operator*(const Matrix<T> &);
        void read();
        void print();

    };
    template <typename T>
    Matrix<T> Matrix<T>::operator=(const Matrix<T> &a){
        if(this->mat!=NULL)
        {
            for(int i = 0 ; i < this->rs ; i++)
                delete []mat;
        }
        this->rs = a.rs;
        this->cs = a.cs;
        this->mat = new T*[a.rs];

        for(int i = 0 ; i < a.rs; i++)
            this->mat[i] = new T[a.cs];

        for(int i = 0 ; i < a.rs ; i++){
            for(int k = 0 ; k < a.cs; k++)
                this->mat[i][k] =a.mat[i][k];
        }
        return a;
    }
    template <typename T>
    Matrix<T> Matrix<T>::operator*(const Matrix<T> &a){
        Matrix<T> b;
        b.rs = this->rs;
        b.cs = a.cs;
        if(this->cs == a.rs){
            b.mat = new T*[b.rs];
            for(int i = 0 ; i < this->rs; i++)
                b.mat[i] = new T[b.cs];

            for(int i = 0 ; i < this->rs; i++)
            {
                for(int k = 0 ; k < a.cs ; k++){
                    b.mat[i][k] = 0;
                    for(int j = 0 ; j < this->cs ; j++)
                        b.mat[i][k] += this->mat[i][j] * a.mat[j][k];
                }
            }
            return b;
        }
        else
        {
               cout<<"You can not multiply these matrices"<<endl;
               b.mat = new T*[b.rs];
            for(int i = 0 ; i < this->rs; i++)
                b.mat[i] = new T[b.cs];
            for(int i = 0 ; i < b.rs ; i++)
                for(int k = 0 ; k < b.cs ; k++)
                    b.mat[i][k] =0;
            return b;
        }

    }
    template <typename T>
    ostream& operator<<(ostream &g ,  Matrix<T> &a);
    template <typename T>
    istream& operator>>(istream &g , Matrix<T> &a);
    int main(){
         Matrix <int > A, B, C;
         Matrix < double > M, R, S;
         cin >> A;
         cin>>C;
         B = A*C;
         cout<<endl<<B<<endl;
    }
    template <typename T>
    ostream& operator<<(ostream &g ,  Matrix<T> &a){
        a.print();
        return g;
    }
    template <typename T>
    void Matrix<T>::print(){
    for(int i = 0; i < rs ;i++){
            for(int k = 0 ; k < cs ; k++){
                cout<<mat[i][k]<<" ";
            }
            cout<<endl;
        }
    }
    template <typename T>
    istream& operator>>(istream &g , Matrix<T> &a)
    {
        a.read();
        return g;
    }
    template <typename T>

    void Matrix<T>::read()
    {
        if (mat!=NULL) {
          for(int i = 0 ; i < rs ; i++)
            delete []mat;
        }
        cout<<"Enter row size: ";
        cin >> rs;
        cout<<"Enter column size: ";
        cin>> cs;
        int i;
        mat = new T*[rs];
        for (i = 0; i < rs; i++)
            mat[i] = new T[cs];
        int j;
        for (i = 0; i < rs; i++)
        {
            for (j = 0; j < cs; j++)
            {
                cout<<"Element ["<<i<<"]"<<"["<<j<<"] = ";
                cin >> mat[i][j];
            }
        }

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2012-11-19
    相关资源
    最近更新 更多