Оператор * = из двух экземпляров (матрица) дает плохие результаты - PullRequest
0 голосов
/ 12 января 2019

У меня есть класс Matrix, и я пытаюсь реализовать оператор метода * =, который я использую, чтобы сделать произведение двух экземпляров (матрицы): m1 * = m2.

Я пробовал оба метода с другом и двумя параметрами, без друга и с одним параметром, но в обоих случаях результаты плохие. Только с одним параметром, и это использование дает мне результаты, похожие на правильные (не всегда).

Пробовал с другом и 2 параметрами и без друга и 1 параметра. Попытка возврата непосредственно первой матрицы m1, а также создание временной матрицы m3

Мои личные участники:

int N, M;      
T** data;
bool Init(const int N_, const int M_);
void Clear();

(я использую init для инициализации матрицы / двумерного массива):

bool Matrix::Init(const int N_, const int M_) {
  this->Clear(); //dealloco comunque prima di inizializzarla
  N = N_;
  M = M_;
  if (N <= 0 || M <= 0) {
      cerr << "Non posso generare una matrixe: " << N <<"x"<< M << endl;
      return false;
  }
  else if (N > 0 && M > 0) {
      data = new T*[N];
      for (int i = 0; i < N; i++) {
        data[i] = new T[M];
      }
  }
return true;

}

Мой оператор * = mathod (нет друга, 1 параметр):

Matrix& Matrix::operator*=(const Matrix& m2) {

    float operation = 0;
    int N_ = (this->N < m2.N) ? this->N : m2.N;
    int M_ = (this->M < m2.M) ? this->M : m2.M;
    Matrix m3(N_, M_);

    if (this->N != m2.M || this->M != m2.N) {
        this->Set(0, 0, flag_stop);
    }
    else {

        for (int i = 0; i < this->N; ++i) {
            for (int j = 0; j < m2.M; ++j) {
                for (int k = 0; k < this->M; ++k) {
                    operation = operation + (this->Get(i,k) * m2.Get(k,j)) ;
                    //cout << " Cout m1 su "<< i<< ","<<k<<":"<< this->Get(i,k) << "\t " << " Cout m2: "<< m2.Get(k,j) << endl;
                    this->Set(i, j, operation);
                }

                //cout << operation << "\t";
                operation = 0;
            }
            operation = 0;
        }
    }
    return *this;
}

В основном, когда я пытаюсь использовать оператор * =:

Matrix m1(i1,j1);
Matrix m2(i2,j2);

//operator*=
    cout << endl;
    m1*=m2;
    int N_ = (m1.GetN() < m2.GetN()) ? m1.GetN() : m2.GetN();
    int M_ = (m1.GetM() < m2.GetM()) ? m1.GetM() : m2.GetM();

    for (int i = 0; i < N_; ++i) {
        for (int j = 0; j < M_; ++j) {
            cout << m1.Get(i,j) << "\t";
        }
        cout << endl;
    }

Я весь день пытаюсь, но результаты не правы я также попробовал с m1 [2] [2] и m2 [2] [2], с m1 [3] [2] и m2 [2] [3] и т. д., но ничего. У кого-то была похожая проблема?

Надеюсь получить правильное произведение двух матриц, но в большинстве случаев у меня большие числа (ожидается 5, получено 30) или правильные числа в первом столбце, а во втором нет

1 Ответ

0 голосов
/ 13 января 2019

Причиной ошибок, о которых вы сообщаете, является сам алгоритм умножения. По сути, ваш код умножения выглядит следующим образом:

for (int i = 0; i < this->N; ++i) {
    for (int j = 0; j < m2.M; ++j) {
        for (int k = 0; k < this->M; ++k) {
            operation = operation + (this->Get(i,k) * m2.Get(k,j)) ;
            this->Set(i, j, operation);
        }
        operation = 0;
    }
}

Ваш алгоритм изменяет исходную матрицу только в процессе вычисления (this->Set() вызов), поэтому при вызове this->Get(i,k) для любого i < j вы получаете не оригинальное значение первой матрицы в i-й строке и k th столбец, но значение, которое уже было изменено вызовом this->Set(). Это, очевидно, приводит к неверным результатам.

Чтобы решить эту проблему, необходимо убедиться, что для расчетов используются исходные значения матрицы, например, путем создания копии исходной матрицы или (более оптимально) измененной в данный момент строки исходной матрицы.

...