【问题标题】:Own matrix class multiply operator自己的矩阵类乘法运算符
【发布时间】:2012-09-29 01:55:03
【问题描述】:

我编写了一个 IntegerMatrix 类来添加我自己的方法来处理矩阵。现在我写了一个这样的函数:

IntegerMatrix** IntegerMatrix::multiplyMatrix(IntegerMatrix** table2)

(这是一个双指针,因为我持有大量指向 4x4 2D 数组的指针。)所以我可以这样做:

matrix1.multplyMatrix(matrix2)

一个小问题是* 没有为我自己的班级定义。所以我想重载这个运算符,我可以做这样的事情:

sum += this->table[i][k] * table2[k][j];

但是我怎样才能在重载运算符中获得正确的ik,其定义如下:

IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & k);

我现在唯一想不通的问题是如何获得正确的值?

编辑:

我已经重写了这个,现在我有:

IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & table2)
{
    int i, j, k;
    int sum;
    IntegerMatrix * result = new IntegerMatrix(SIZE);

    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            sum = 0;
            for (k = 0; k < SIZE; k++) {
                sum += this->table[i][k] * table2[k][j];
            }
            result[i][j] = sum;
        }
    }
    return *result;

}

这只是在 [] 上给我一个错误:

Binary '[' : 'IntegerMatrix' does not define this operator or a conversiont o a type acceptable to the predefined operator.

【问题讨论】:

  • 为什么你的乘法函数使用双指针而不是引用?当您尝试您建议的 operator* 时,您遇到了哪些错误?为什么矩阵乘法应该知道ik?我完全不明白这个问题。
  • 你确定你应该为二维数组使用动态内存来进行乘法和其他操作吗?
  • 不解释原因而投反对票的人是愚蠢的。
  • sum += this-&gt;table[i][k] * table2[k][j]; 似乎是两个整数相乘,与矩阵乘法完全无关。 @Wug:也许他们确实发表了评论。
  • 我没有说评论,我说解释。我没有看到任何说“-1 因为 X”的东西。刻意教人有助于他们学习,但不是,不会。这个问题本身的形式相当好,是一个关于特定算法的实用、可回答的问题。 (尽管有风格。)如果你看到某人的风格让你感到震惊,那么向他们展示好的风格是什么样子会更有帮助,而不是仅仅暗示他们错了。

标签: c++ operator-overloading matrix-multiplication


【解决方案1】:

对于一个IntegerMatrix 对象,您使用this-&gt;table[i][k] 来引用您保存矩阵数据的数组,而对于table2 对象引用和result 指针,您使用的是@ 987654325@ 和result[i][j]

我认为您想要做的是:

IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & table2)
{
    int i, j, k;
    int sum;
    IntegerMatrix * result = new IntegerMatrix(SIZE);

    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            sum = 0;
            for (k = 0; k < SIZE; k++) {
                sum += this->table[i][k] * table2.table[k][j];
            }
            result->table[i][j] = sum;
        }
    }
    return *result;
}

【讨论】:

    【解决方案2】:

    您可能会携带一些人工制品,有点像Cargo-Cult programming。 :-/

    例如:我猜你的 multiplyMatrix 原型上的双重间接寻址 (**) 存在,因为你在某处看到了整数的多维数组...类似的东西:

    void printMatrix(int ** myMatrix, int rows, int columns);
    

    双重间接只是一个指向指针的指针。是实现passing low-level C-style 2D arrays as parameters具体实现点的一种方式。但是,当您使用碰巧代表矩阵的抽象类时,您不必执行此操作。因此,一旦您将矩阵大小和数据本身封装在 IntegerMatrix 类中,您就不需要这样的东西了:

    void printMatrix(IntegerMatrix ** myMatrix);
    

    您更有可能希望传递对封装数据的类的简单引用,如下所示:

    void printMatrix(IntegerMatrix const & myMatrix);
    

    您实际上应该从乘法函数返回一个新矩阵,至少如果您使用它来实现运算符重载...因为从语义上讲,人们编写像a * b; 这样的东西并拥有它是没有意义的修改一个。 (它可以,但你不应该。)所以你可以选择返回一个矩阵值实例:

    IntegerMatrix IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);
    

    ...或者返回一个指向新对象的指针:

    IntegerMatrix * IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);
    

    历史上许多库都选择通过指针返回,因为从函数中的局部变量按值返回将涉及在返回时进行复制。返回指针很快(它只“复制”一个 32 位/64 位数字),而复制对象实例和其中的大数据块很慢。所以很多库只会在任何地方使用矩阵指针......问题是很难知道最终delete对象是谁的责任。智能指针是确保这一点的一种方法:

    unique_ptr<IntegerMatrix> IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);
    

    但是 C++11 有一些鬼鬼祟祟的能力,可以在没有混乱的情况下保持同样的速度。如果您从函数中按值返回某些内容,并且编译器确定不会再次使用该值(因为它超出了范围),那么它可以像指针一样快地“移动”。这就要求你支持RValue reference的移动构造,这里面有各种各样的技巧。

    确实有很多细微差别。如果您将此作为一种教育练习,我建议您慢慢来,并阅读一个指导您完成每一步的教程,而不是直接跳入火中。如果您在矩阵中使用低级 C 数组和动态分配,请将它们更改为 std::vectorstd::vector

    【讨论】:

      【解决方案3】:

      我不明白你的问题,但这里有一个关于矩阵乘法正常工作原理的简短演示:

      class IntegerMatrix {
          int table[3][3];
      
      public:
            IntegerMatrix& operator*=(const IntegerMatrix& rhs) {
                 //multiply table by rhs.table, store in data.
                 return *this;
            }
      };
      IntegerMatrix operator*(IntegerMatrix lhs, const IntegerMatrix& rhs)
      {return lhs*=rhs;} //lhs is a copy, so we can alter and return it
      

      供您编辑

      你有密码

      IntegerMatrix * result = new IntegerMatrix(SIZE); //pointer to an IntegerMatrix
      ...
      result[i][j] = sum; //assign sum to the jth index of matrix # i
      

      实际上,我想你想要

      result->table[i][j] = sum; //sum to the ixj index of the result matrix.
      

      另外,你的函数是泄漏的,因为你有一个new,但没有delete。在您的情况下这很容易解决,因为您不需要新的。 (您是 Java 还是 C# 背景?)

      IntegerMatrix result(SIZE);
      ...
              result[i][j] = sum;
      ...
      return result;
      

      与上述所有内容无关,您实际上可能希望为您的整数矩阵提供 [] 运算符。

      class row {
          int* data;
          int size;
      public:
          row(int* d, int s) :data(d), size(s) {}
          int& operator[](int offset) {
              assert(offset<size);
              return data[offset];
          }
      };
      
      row operator[](int column) {
          assert(column<SIZE); 
          return row(table[column], SIZE);
      }
      

      这将允许你写:

      IntegerMatrix result;
      result[i][j] = sum;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多