运算符重载矩阵乘法



我遇到的问题是如何获得正确的数字列,以通过K的最内层循环。一个例子是2x3矩阵和3x2矩阵相乘。结果应该是一个2x2矩阵,但目前我不知道如何将2的值发送到操作符重载函数。应该是Int k = 0;k & lt;第一个矩阵的列数;k++

Matrix::Matrix(int row, int col)
{
rows = row;
cols = col;
cx = (float**)malloc(rows * sizeof(float*));  //initialize pointer to pointer matrix
for (int i = 0; i < rows; i++)
*(cx + i) = (float*)malloc(cols * sizeof(float));
}

Matrix Matrix::operator * (Matrix dx)
{
Matrix mult(rows, cols);
for (int i = 0; i < rows; i++)
{ 
for (int j = 0; j < cols; j++)
{
mult.cx[i][j] = 0;
for (int k = 0; k < ?;k++) //?????????????
{
mult.cx[i][j] += cx[i][k] * dx.cx[k][j];
}
}
}
mult.print();
return mult;

//calling
Matrix mult(rowA, colB);
mult = mat1 * mat2;
}

线性代数规则规定结果的维度应该是行x dx.cols

Matrix Matrix::operator * (Matrix dx)
{
Matrix mult(rows, dx.cols);
for (int i = 0; i < rows; i++)
{ 
for (int j = 0; j < cols; j++)
{
mult.cx[i][j] = 0;
for (int k = 0; k < cols;k++) //?????????????
{
mult.cx[i][j] += cx[i][k] * dx.cx[k][j];
}
}
}
mult.print();
return mult;

一些随机提示:

  • 你的代码基本上是C;它没有使用(例如)c++中重要的内存安全特性。(操作符重载是唯一使用的类c++特性。)我建议你多利用一点c++。
  • c++中严格避免使用malloc()。使用std::make_unique(...),或者,如果没有其他方法,使用原始new操作符。(顺便说一句,总有另一种方式。)在后一种情况下,确保有一个deletedelete[]的析构函数。在代码片段中使用malloc()就像内存泄漏。
  • 可以const应该const。在构造函数的初始化列表中初始化尽可能多的类成员,如果合适,将它们设为const。(例如,Matrix尺寸不改变,应该是const。)
  • 当编写类似容器的类时(在某种意义上,Matrix可能是),不要将其限制为单一数据类型;未来的自己会感谢你的。(如果你需要一个double而不是float呢?这是一个一行的编辑还是一个通宵的搜索,一个被遗忘的float侵蚀了你的精度?)

下面是一个显示矩阵乘法的快速且可运行的示例:

#include <cstddef>
#include <iomanip>
#include <iostream>
#include <memory>
namespace matrix {
using std::size_t;
template<typename Element>
class Matrix {
class Accessor {
public:
Accessor(const Matrix& mat, size_t m) : data_(&mat.data_[m * mat.n_]) {}
Element& operator [](size_t n) { return data_[n]; }
const Element& operator [](size_t n) const { return data_[n]; }
private:
Element *const data_;
};
public:
Matrix(size_t m, size_t n) : m_(m), n_(n),
data_(std::make_unique<Element[]>(m * n)) {}
Matrix(Matrix &&rv) : m_(rv.m_), n_(rv.n_), data_(std::move(rv.data_)) {}
Matrix operator *(const Matrix& right) {
Matrix result(m_, right.n_);
for (size_t i = 0; i < m_; ++i)
for (size_t j = 0; j < right.n_; ++j) {
result[i][j] = Element{};
for (size_t k = 0; k < n_; ++k) result[i][j] +=
(*this)[i][k] * right[k][j];
}
return result;
}
Accessor operator [](size_t m) { return Accessor(*this, m); }
const Accessor operator [](size_t m) const { return Accessor(*this, m); }
size_t m() const { return m_; }
size_t n() const { return n_; }
private:
const size_t m_;
const size_t n_;
std::unique_ptr<Element[]> data_;
};
template<typename Element>
std::ostream& operator <<(std::ostream &out, const Matrix<Element> &mat) {
for (size_t i = 0; i < mat.m(); ++i) {
for (size_t j = 0; j < mat.n(); ++j) out << std::setw(4) << mat[i][j];
out << std::endl;
}
return out;
}
}  // namespace matrix
int main() {
matrix::Matrix<int> m22{2, 2};
m22[0][0] = 0;  // TODO: std::initializer_list
m22[0][1] = 1;
m22[1][0] = 2;
m22[1][1] = 3;
matrix::Matrix<int> m23{2, 3};
m23[0][0] = 0;  // TODO: std::initializer_list
m23[0][1] = 1;
m23[0][2] = 2;
m23[1][0] = 3;
m23[1][1] = 4;
m23[1][2] = 5;
matrix::Matrix<int> m32{3, 2};
m32[0][0] = 5;  // TODO: std::initializer_list
m32[0][1] = 4;
m32[1][0] = 3;
m32[1][1] = 2;
m32[2][0] = 1;
m32[2][1] = 0;
std::cout << "Original:nn";
std::cout << m22 << std::endl << m23 << std::endl << m32 << std::endl;
std::cout << "Multiplied:nn";
std::cout << m22 * m22 << std::endl
<< m22 * m23 << std::endl
<< m32 * m22 << std::endl
<< m23 * m32 << std::endl
<< m32 * m23 << std::endl;
}

可能的改进和其他建议:

  • 添加一致性检查。例如,throw,当维度不匹配乘法时的std::invalid_argument,即m_ != right.n_,以及operator []得到越界参数时的std::range_error。(检查可能是可选的,激活(例如)使用if constexpr调试。)
  • 使用std::initializer_list或类似的初始化,以便您可以(例如)在行中初始化const Matrix
  • 总是
  • 使用valgrind检查代码。(提示:使用-g构建让valgrind也打印错误发生的行号(或相关的先前(de)分配发生的行号)。)
  • 代码可以做得更短更优雅(不一定更高效;通过而不是到处使用operator [],并且使用指针算术来代替,编译器优化是神奇的。
  • 使类型系统更好,这样(例如)不同类型的Matrix实例可以很好地相互配合。也许一个Matrix<int>乘以一个Matrix<double>可以得到一个Matrix<double>等等。还可以支持标量值与Matrix之间的乘法。或者在Matrixstd::arraystd::vector等之间

相关内容

  • 没有找到相关文章

最新更新