【问题标题】:Matrix - return and pass as parameter c++矩阵 - 返回并作为参数传递 c++
【发布时间】:2017-11-16 22:09:58
【问题描述】:

我正在尝试使用 clear 函数与随机生成的值进行矩阵乘法。因此,当矩阵作为参数发送时,我希望使用一个函数(mat_def)生成矩阵,并使用另一个函数(mat_mul)将它们相乘。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

using namespace std;

double mat_def(int n) //how to return the matrix
{
    double a[n][n];

    double f; 

    for(int i=0; i<n;  i++)
    {
        for(int j=0; j<n; j++)
        {
            f= rand();
            cout<<f ;
            a[i][j]=f;
        }

    }

    return 0;
}


double mat_mul( int n, double a[n][n], double b[n][n]) //how to send matrix as parameter
{
    return 0;
}


int main()
{
    /* initialize random seed: */
    srand (time(NULL));
    mat_def(10); 
}

【问题讨论】:

  • 您的问题是什么?你想知道如何将两个矩阵相乘或其他什么吗?
  • 在 C++ 中实现 Matrix 类的方法有很多。经典地,查找重载::operator[] 并返回对内部类的引用,该内部类也重载::operator[],因此您可以使用实际的矩阵语法。
  • 给您的问题:矩阵的大小在编译时是否已知?矩阵是否应该只是方阵?

标签: c++ matrix matrix-multiplication


【解决方案1】:

这是一个不错的标准 C++ 矩阵模板。

Matrix.h

#include <vector>

class Matrix
{
    class InnerM
    {
        private:
           int ydim;
           double* values;

        public:
            InnerM(int y) : ydim(y)
            {
                values = new double[y];
            }

            double& operator[](int y)
            {
                return values[y];
            }
    };

    private:
       int xdim;
       int ydim;

       std::vector<InnerM> inner;

    public:

       Matrix(int x, int y) : xdim(x), ydim(y), inner(xdim, InnerM(ydim))
       {
       }

       InnerM& operator[](int x)
       { 
           return inner[x];
       }
};

所有的内存泄漏都在那里,但你明白了。从这里您可以通过在 Matrix 类中覆盖 ::operator*() 来处理乘法。

【讨论】:

  • 类是正确的方法,但还有一些改进的空间。 InnerM 需要一个析构函数。现在它泄漏了。修复后,您可能会注意到它不符合the Rule of Three,这可能会导致稍后出现错误喜剧。到目前为止,这两个问题的最佳解决方案是另一个 std::vector。最后一个改进是性能调整问题。通过让vector 包含动态分配,您将失去存储的连续性并影响缓存友好性。
  • 当然,就像我说的,我只是吐了一些东西。
【解决方案2】:

我假设您的问题是定义二维数组,然后将其传递给 mat_mul 函数以将矩阵相乘。剩下的就很简单了。

定义二维数组(考虑内存需求在运行时已知):

    int rows,cols;
    cin >> rows;
    cin >> cols;

    int **arr = new int*[rows];          // rows X cols 2D-array 
    for(int i = 0; i < rows; ++i) {
        arr[i] = new int[cols];
    }

您可以使用所需的行和列以完全相同的方式定义另一个二维数组。

现在,将二维数组传递给函数:

void mat_mul(int **arr1, int **arr2, int m, int n, int p, int q){
    //define a 2-D array to store the result
    //do the multiplication operation
    //you could store the result in one of the two arrays
    //so that you don't have to return it 
    //or else the return type should be modified to return the 2-D array
}

示例:

void display(int **arr, int row, int col){
    for (int i=0; i<row; i++){
        for(int j=0;j<col; j++){
            cout << arr[i][j] << '\t';
        }
        cout << endl;
    }
}

如果不再需要,使用以下语法删除内存:

for(int i=0; i<rows; i++){
  delete[] array[i];
}
delete[] array;

希望这足以完成您的工作!

关于如何在 SO 上返回二维数组已经有了答案。检查下面的链接。

https://stackoverflow.com/a/8618617/8038009

【讨论】:

  • 不要将数组数组用于矩阵。传递速度很慢,很烦人,并且将所有内存管理都转储给了程序员。至少将它包装在一个类中。
【解决方案3】:

退回原始分配是一个傻瓜赌注。您需要管理自己分配的所有内存并使用矩阵大小参数传递它。

为什么要受苦?使用矩阵类

template<class Type>
class Matrix{
    int rows;
    int cols;
    std::vector<type> data;
public:
    Matrix(int row, int col):rows(row), cols(col), data(rows*cols)
    {
        // does nothing. All of the heavy lifting was in the initializer
    }
    // std::vector eliminates the need for destructor, assignment operators, and copy 
    //and move constructors.
    //add a convenience method for easy access to the vector
    type & operator()(size_t row, size_t col)
    {
        return data[row*cols+col];
    } 
    type operator()(size_t row, size_t col) const
    {
        return data[row*cols+col];
    } 
};

用法是

Matrix<double> mat_mul(const Matrix<double> &a, const Matrix<double> &b) 
{
    Matrix<double> result;
    // do multiplication 

    return result;
}

int main()
{
    /* initialize random seed: */
    srand (time(NULL));
    Matrix<double> matA(10, 10); 
    matA(0,0) = 3.14; // sample assignment
    matA(9,9) = 2.78;
    double x = matA(0,0) * matA(9,9)
    Matrix<double> matB(10, 10); 

    Matrix<double> matC = mat_mul(matA, matB) ;
}

更多功能,例如从initializer list 构造,可以添加到类中,让您的生活更轻松。您还可以为Matrix 指定operator * 重载,如果您愿意,可以使用它来代替mat_mul。阅读Operator overloading 了解有关该选项的更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2022-10-12
    相关资源
    最近更新 更多