2015-08-20 105 views
1

我已經實現了矩陣類。它爲任意大小的矩陣動態分配內存。當使用我的矩陣乘法函數時,它只能在特定條件下工作。如果您有兩個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; 
} 

爲什麼不能在這些環境下工作的計劃?

+1

好消息是,您沒有[代碼三](https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming))代碼中的問題,因爲您'重新實現*析構函數,copy-ctor或copy-assignment操作符。壞消息是,*原因*這不是問題,因爲它像篩子一樣泄漏。 – WhozCraig

回答

2

首先,要對

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將證明絕對沒有。

我建議用

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

更換

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>)) 
{ 
} 
+0

作爲獎勵,使用'std :: vector <>'方法使得類規則 - -three符合默認。 ',0'不是必需的,但是這是非常值得一提的。此外,雖然它不影響此代碼,但應該注意,該成員列表中的初始化程序的順序不是*從左到右。 'rows',然後'cols',然後'data'將是類decl中每個成員的順序的初始化順序。 – WhozCraig

+0

是的,0幾乎沒用。我會編輯以清楚說明爲什麼你可能想在那裏指定一個值。和軟糖。我確實弄錯了訂單。我正在查看行和列函數。 – user4581301

+0

這很棒。清楚地解決問題並提供解決方案。謝謝。 – Anandamide

1

這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; 
     } 
    } 
+2

想想在將1x1矩陣乘以1x1矩陣時這會發生什麼 – WhozCraig

+0

我不認爲OP正在查看其函數的輸出。 – user4581301

+0

@ user4581301我對此也有嚴肅的保留。如果使用這裏提出的解決方案,我建議的例子完全不會導致乘法運算和1x1矩陣運算,無論操作數如何,單個值爲零。這顯然*不正確。 – WhozCraig

0

我希望這段代碼能夠正常工作。

#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]; 
      } 
     } 

    }