다음은 행렬 곱셈을 수행하는 C++ 언어 소스이다.

행의 수, 열의 수. 그리고 두 행렬의 요소들을 모두 컨솔에서 입력해야 한다.

소스는 http://www.physics.utah.edu/~detar/lessons/c++/matrices/node4.html 의 것을 다소 수정한 것이다.

 

// Filename: testSomeMat-03.cpp
//
// Copmpile: cl /EHsc testSomeMat-03.cpp
// Execute: testSomeMat-03
//
// Date: 2003.9. 20.

#include <iostream>
#include <vector>
#include <iomanip>
 
using namespace std;

typedef vector<double> Vec;
typedef vector<Vec> Mat;

Vec operator*(const Mat &a, const Vec &x){
  int i,j;
  int m = a.size();
  int n = x.size();

  Vec prod(m);

  for(i = 0; i < m; i++){
    prod[i] = 0.;
    for(j = 0; j < n; j++)
      prod[i] += a[i][j]*x[j];
  }
  return prod;
}

Mat operator*(const Mat &a, const Mat &b) {
  int i, j, k;
  int m = a.size();
  int n = a[0].size();
  int p = b[0].size();

  Mat c;

  for(i = 0; i < m; i++){
    Vec row(p);
    for(j = 0; j < p; j++) {
      row[j] = 0.;
      for(k = 0; k < n; k++) {
          row[j] += a[i][k]*b[k][j];
      }
    }
    c.push_back(row);
  }
  return c;
}

void printMatrix(const Mat &a, int width) {
  int i, j;
  int m = a.size();
  int n = a[0].size();

  for(i = 0; i < m; i++) {
     if (i == 0)
        cout << "  [[";
     else
        cout << "   [";
      for(j = 0; j < n; j++) {
        cout << "  " << setw(width) << a[i][j];
      }
     if (i < m - 1)
          cout << "  ]";
     else
          cout << "  ]]";
      cout << "\n";
  }
}

int main() {

  int i, j, k, m, n, p;

  cout << "첫째 행렬의 행의 수: ";
  cin >> m;
  cout << "첫째 행렬의 열의 수: ";
  cin >> n;
  cout << "둘째 행렬의 열의 수: ";
  cin >> p;

  cout << "\n";
  
  // 첫째 행렬과 이 행렬의 입력을 위한 벡터 선언
  Mat a;
  Vec row(n);

  cout << "첫째 행렬의 요소들을 입력하시오.\n";
  for(i = 0; i < m; i++){
    for(j = 0; j < n; j++)cin >> row[j];
    a.push_back(row);
  }

  // 둘째 행렬과 이 행렬의 입력을 위한 벡터 선언
  Mat b;
  Vec row2(p);

  cout << "둘째 행렬의 요소들을 입력하시오.\n";
  for(i = 0; i < n; i++){
    for(j = 0; j < p; j++)cin >> row2[j];
    b.push_back(row2);
  }


  Mat c = a*b;

  cout << "\nA = \n";
  printMatrix(a, 8);

  cout << "\nB = \n";
  printMatrix(b, 8);

  cout << "\nA*B = \n";
  printMatrix(c, 8);

  return 0;
}

/*
Output:
첫째 행렬의 행의 수: 3
첫째 행렬의 열의 수: 3
둘째 행렬의 열의 수: 1

첫째 행렬의 요소들을 입력하시오.
 2  5 6
1 2 0
9 7 1
둘째 행렬의 요소들을 입력하시오.
4 1 2

A =
  [[         2         5         6  ]
   [         1         2         0  ]
   [         9         7         1  ]]

B =
  [[         4  ]
   [         1  ]
   [         2  ]]

A*B =
  [[        25  ]
   [         6  ]
   [        45  ]]
*/

 

 

다음은 정사각행렬의 행렬식을 구하는 소스이다.

// Filename: determinant-04.cpp
//
// Compile: g++ -std=c++11 -o determinant-04 determinant-04.cpp
// Execute: ./determinant-04
//
//     or
//
// Compile: cl /EHsc determinant-04.cpp
// Execute: determinant-04
//
// Date: 2013. 9. 20.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <cstring>

using namespace std;

typedef vector<double> Vec;
typedef vector<Vec> Mat;

Vec operator*(const Mat &a, const Vec &x){
  int i,j;
  int m = a.size();
  int n = x.size();

  Vec prod(m);

  for(i = 0; i < m; i++){
    prod[i] = 0.;
    for(j = 0; j < n; j++)
      prod[i] += a[i][j]*x[j];
  }
  return prod;
}

Mat operator*(const Mat &a, const Mat &b) {
  int i, j, k;
  int m = a.size();
  int n = a[0].size();
  int p = b[0].size();

  Mat c;

  for(i = 0; i < m; i++){
    Vec row(p);
    for(j = 0; j < p; j++) {
      row[j] = 0.;
      for(k = 0; k < n; k++) {
          row[j] += a[i][k]*b[k][j];
      }
    }
    c.push_back(row);
  }
  return c;
}

void printMatrix(const Mat &a, int width) {
  int i, j;
  int m = a.size();
  int n = a[0].size();

  for(i = 0; i < m; i++) {
     if (i == 0)
        cout << "  [[";
     else
        cout << "   [";
      for(j = 0; j < n; j++) {
        cout << "  " << setw(width) << a[i][j];
      }
     if (i < m - 1)
          cout << "  ]";
     else
          cout << "  ]]";
      cout << "\n";
  }
}

void printPermutation(const vector<int> pmt, int counter)
{
    int n = pmt.size();
    cout << "[";
    if (n > 0)
    {
        cout << " " << pmt[0];
        if (n > 1)
        {
            for (int i = 1; i < n; i++)
            {
                cout << ", " << pmt[i];
            }
        }
        cout << " ";
    }
    cout << "]";
    if ((counter % 2) == 0)
        cout << "    -- even --";
    else
        cout << "    -- odd  --";
    cout << endl;
}

void swap(vector<int> &pmt, int i, int j)
{
    int x = pmt[j];
    pmt[j] = pmt[i];
    pmt[i] = x;
}


 

void doPermute(const Mat &mat, int dim, vector<int> pmt, int size, int &cnt, double &det, bool show_flag)
{
    double x;
    double y;
    if (size == 2)
    {
       if (show_flag)
            printPermutation(pmt, cnt);
        x = 1.0;
        for (int j = 0; j < dim; j++)
        {
         if (mat[j][pmt[j]] == 0) {
          x = 0;
          break;
         }
         x *= mat[j][pmt[j]];
        }
        det += ((cnt % 2) == 0) ? x : -x;
        swap(pmt, 0, 1);
        cnt++;
        if (show_flag)
            printPermutation(pmt, cnt);
        x = 1.0;
        for (int j = 0; j < dim; j++)
        {
           if (mat[j][pmt[j]] == 0) {
          x = 0.0;
          break;
         }
        x *= mat[j][pmt[j]];
        }
        det += ((cnt % 2) == 0) ? x : -x;
        swap(pmt, 0, 1);
        cnt--;
    }
    else if (size > 2)
    {
        doPermute(mat, dim, pmt, size - 1, cnt, det, show_flag);
        for (int i = size - 2; i >= 0; i--)
        {
             swap(pmt, i, size - 1);
             cnt++;
             doPermute(mat, dim, pmt, size - 1, cnt, det, show_flag);
        }
        for (int i = 0; i <= size - 2; i++)
        {
            swap(pmt, i, size - 1);
            cnt--;
        }
    }
}

int main(int argc, const char *argv[])
{
    // vector<int> v = { 0, 1, 2, 3, 4 };     // syntax for C++11
    vector<int> v(5);
    for (int i = 0; i < 5; i++)
    {
     v[i] = i;
    }
   
    int counter = 0;
    int dim = 3;
    int n = 3;
    double d = 0.0;
    
    cout << "정사각행렬의 행의 수: ";
    cin >> n;

     // Allocate space for the vectors
     Mat a;
     Vec row(n);

     cout << "행렬의 모든 요소를 입력하시오.\n";
     for (int i = 0; i < n; i++) {
         for (int j = 0; j < n; j++) {
             cin >> row[j];
         }
         a.push_back(row);
     }

     cout << "\nA = \n";
     printMatrix(a, 8);


    if (n > 5)
    {
        for (int i = 5; i < n; i++)
        {
            v.push_back(i);
        }
    }
    else if (n < 5) {
       for (int i = 0; i < 5 - n; i++)
       {
          v.pop_back();
       }
    }

    dim = n;


    cout << endl;
    
    bool show_flag = false;    // true;    // false;
    doPermute(a, dim, v, n, counter, d, show_flag);

    if (show_flag)
        cout << endl;
    cout << "A의 행렬식: det(A) = " << d << endl;
    return 0;
}

/*
Execute & Output:
정사각행렬의 행의 수: 2
행렬의 모든 요소를 입력하시오.
7 8
9 2

A =
  [[         7         8  ]
   [         9         2  ]]

A의 행렬식: det(A) = -58
*/

 

 

Posted by Scripter
,

정리 (정사각행렬의 행렬식, derterminant)

n × n 행렬 A = \big( a_{ij} \big) 의 행렬식 \det(A) 는 다음 식과 같다

         \det(A) \ = \ \sum_{\sigma} \, \textrm{sign}(\sigma) \, a_{1 \sigma(1)} a_{2 \sigma(2)} \cdots a_{n \sigma(n)}

위에서 합은 집합 \{ 1, 2, \cdots, n \} 위에서의 모든 순열 \sigma에 관한 합이며, \textrm{sign}(\sigma)\sigma가 우순열인 경우에는 +1이고, 기순열인 경우에는 -1이다.

 

다음의 C++ 언어로 작성된 소스는 순열을 출력하는 소스를 수정아여 정사각행렬의 행렬식을 계산하도록 하였다.

컴파일은 g++ 또는 Visual C++ 의 명령줄 컴파일러 cl 을 이용한다.

 

// Filename: determinant-03.cpp
//
// Compile: g++ -std=c++11 -o determinant-03 determinant-03.cpp
// Execute: ./determinant-03 [integer]
//
//     or
//
// Compile: cl /EHsc determinant-03.cpp
// Execute: determinant-03 [integer]
//
// Date: 2013. 9. 20.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <cstring>

using namespace std;

template<typename T>
class Array2D
{
    private:
        const int width;
        T * data;
    public:
        T& operator() (int x, int y) { return data[y*width + x]; }
        Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
        ~Array2D() { delete [] data; }
};

void printPermutation(const vector<int> pmt, int counter)
{
    int n = pmt.size();
    cout << "[";
    if (n > 0)
    {
        cout << " " << pmt[0];
        if (n > 1)
        {
            for (int i = 1; i < n; i++)
            {
                cout << ", " << pmt[i];
            }
        }
        cout << " ";
    }
    cout << "]";
    if ((counter % 2) == 0)
        cout << "    -- even --";
    else
        cout << "    -- odd  --";
    cout << endl;
}

void swap(vector<int> &pmt, int i, int j)
{
    int x = pmt[j];
    pmt[j] = pmt[i];
    pmt[i] = x;
}

void printMatrix(Array2D<double> &mat, int nrow, int ncol)
{
    for (int i = 0; i < nrow; i++)
    {
        cout << "[[";
        for (int j = 0; j < ncol; j++)
        {
            cout << " " << setw(9) << mat(i, j) << " ";
        }
        cout << "  ]]" << endl;
    }
    cout << endl;
}

#include <sstream>
void readMatrix(Array2D<double> &mat, int nrow, int ncol)
{
  std::string line;
     double x;
     int i = 0;
     while (i < nrow*ncol)
     {
          cin >> line;
          std::istringstream iss(line);
          while (iss)
          {
              std::string sub;
              iss >> sub;

              std::istringstream ins(sub);
              if (!(ins >> x))
                  break;
              mat(i / ncol, i % ncol) = x;
              i++;
          }
     }
}

void doPermute(Array2D<double> &mat, int dim, vector<int> pmt, int size, int &cnt, double &det, bool show_flag)
{
    double x;
    double y;
    if (size == 2)
    {
       if (show_flag)
            printPermutation(pmt, cnt);
        x = 1.0;
        for (int j = 0; j < dim; j++)
        {
         if (mat(j, pmt[j]) == 0) {
          x = 0;
          break;
         }
         x *= mat(j, pmt[j]);
        }
        det += ((cnt % 2) == 0) ? x : -x;
        swap(pmt, 0, 1);
        cnt++;
        if (show_flag)
            printPermutation(pmt, cnt);
        x = 1.0;
        for (int j = 0; j < dim; j++)
        {
           if (mat(j, pmt[j]) == 0) {
          x = 0.0;
          break;
         }
        x *= mat(j, pmt[j]);
        }
        det += ((cnt % 2) == 0) ? x : -x;
        swap(pmt, 0, 1);
        cnt--;
    }
    else if (size > 2)
    {
        doPermute(mat, dim, pmt, size - 1, cnt, det, show_flag);
        for (int i = size - 2; i >= 0; i--)
        {
             swap(pmt, i, size - 1);
             cnt++;
             doPermute(mat, dim, pmt, size - 1, cnt, det, show_flag);
        }
        for (int i = 0; i <= size - 2; i++)
        {
            swap(pmt, i, size - 1);
            cnt--;
        }
    }
}

int main(int argc, const char *argv[])
{
    // vector<int> v = { 0, 1, 2, 3, 4 };     // syntax for C++11
    vector<int> v(5);
    for (int i = 0; i < 5; i++)
    {
     v[i] = i;
    }
   
    int counter = 0;
    int dim = 3;
    int k = 3;
    double d = 0.0;


    if (argc > 1)
    {
        sscanf(argv[1], "%d", &k);
    }

    if (k > 5)
    {
        for (int i = 5; i < k; i++)
        {
            v.push_back(i);
        }
    }
    else if (k < 5) {
       for (int i = 0; i < 5 - k; i++)
       {
          v.pop_back();
       }
    }

    dim = k;
    Array2D<double> mat(dim, dim);

    cout << "Input a " << k << " by " << k << " matrix" << endl;

    readMatrix(mat, k, k);

    cout << endl;
    cout << "The given matrix is " << endl;
    printMatrix(mat, dim, dim);
   
    bool show_flag = false;
    doPermute(mat, dim, v, k, counter, d, show_flag);

    if (show_flag)
        cout << endl;
    cout << "Its determinant is " << d << "." << endl;
    return 0;
}

/*
Execute & Output:
명령프롬프트> determinant-03
Input a 3 by 3 matrix
1 2 3   4 5 6.02   7 8.1   9

The given matrix is
[[         1          2          3   ]]
[[         4          5       6.02   ]]
[[         7        8.1          9   ]]

Its determinant is 0.718.

명령프롬프트> determinant-03 2
Input a 2 by 2 matrix
7 8
0.1 5.1

The given matrix is
[[         7          8   ]]
[[       0.1        5.1   ]]

Its determinant is 34.9.

명령프롬프트> determinant-03 4
Input a 4 by 4 matrix
1 2 3   4 5 6.02   7 8.1   9
0 0 0 7 0 2 3

The given matrix is
[[         1          2          3          4   ]]
[[         5       6.02          7        8.1   ]]
[[         9          0          0          0   ]]
[[         7          0          2          3   ]]

Its determinant is 32.22.
*/

 

 

 

Posted by Scripter
,