Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++로 구현하는 행렬 곱셈 프로그램 – 단계별 코드 예제와 상세 설명

행렬이란 무엇인가?

행렬(matrix)은 숫자들을 행(row)열(column)의 직사각형 형태로 배열한 것입니다. 행렬은 선형대수학의 기본 개념으로, 그래픽 처리, 머신러닝, 과학 계산 등 다양한 분야에서 널리 활용됩니다.

예를 들어, 아래와 같은 3×2 행렬은 3개의 행과 2개의 열로 구성되어 있습니다.

8 1
4 9
5 6

두 행렬의 곱셈이 성립하려면 첫 번째 행렬의 열 개수와 두 번째 행렬의 행 개수가 반드시 같아야 합니다. 결과 행렬의 각 원소는 첫 번째 행렬의 행 원소들과 두 번째 행렬의 열 원소들을 서로 곱한 뒤 모두 더한 값이 됩니다.

그럼 행렬 곱셈을 수행하는 C++ 프로그램을 살펴보겠습니다.

전체 예제 코드

#include<iostream>
using namespace std;
int main() {
   int product[10][10], r1=3, c1=3, r2=3, c2=3, i, j, k;
   int a[3][3] = { {2, 4, 1} , {2, 3, 9} , {3, 1, 8} };
   int b[3][3] = { {1, 2, 3} , {3, 6, 1} , {2, 4, 7} };
   if (c1 != r2) {
      cout<<"첫 번째 행렬의 열 개수는 두 번째 행렬의 행 개수와 같아야 합니다";
   } else {
      cout<<"첫 번째 행렬:"<<endl;
      for(i=0; i<r1; ++i) {
         for(j=0; j<c1; ++j)
         cout<<a[i][j]<<" ";
         cout<<endl;
      }
      cout<<endl;
      cout<<"두 번째 행렬:"<<endl;
      for(i=0; i<r2; ++i) {
         for(j=0; j<c2; ++j)
         cout<<b[i][j]<<" ";
         cout<<endl;
      }
      cout<<endl;
      for(i=0; i<r1; ++i)
      for(j=0; j<c2; ++j) {
         product[i][j] = 0;
      }
      for(i=0; i<r1; ++i)
      for(j=0; j<c2; ++j)
      for(k=0; k<c1; ++k) {
         product[i][j]+=a[i][k]*b[k][j];
      }
      cout<<"두 행렬의 곱:"<<endl;
      for(i=0; i<r1; ++i) {
         for(j=0; j<c2; ++j)
         cout<<product[i][j]<<" ";
         cout<<endl;
      }
   }
   return 0;
}

실행 결과

첫 번째 행렬:
2 4 1
2 3 9
3 1 8
두 번째 행렬:
1 2 3
3 6 1
2 4 7
두 행렬의 곱:
16 32 17
29 58 72
22 44 66

코드 단계별 설명

1단계: 행렬 초기화

위 프로그램에서는 두 개의 3×3 행렬 a와 b를 선언과 동시에 다음과 같이 초기화합니다.

int a[3][3] = { {2, 4, 1} , {2, 3, 9} , {3, 1, 8} };
int b[3][3] = { {1, 2, 3} , {3, 6, 1} , {2, 4, 7} };

2단계: 곱셈 가능 여부 검사

첫 번째 행렬의 열 개수(c1)가 두 번째 행렬의 행 개수(r2)와 일치하지 않으면 행렬 곱셈을 정의할 수 없습니다. 이 경우 프로그램은 연산을 진행하지 않고 오류 메시지를 출력합니다.

if (c1 != r2) {
   cout<<"첫 번째 행렬의 열 개수는 두 번째 행렬의 행 개수와 같아야 합니다";
}

3단계: 행렬 출력하기

두 행렬 a와 b는 중첩 for 루프를 사용하여 화면에 출력됩니다. 바깥쪽 루프가 행을 순회하고, 안쪽 루프가 각 행의 열 원소를 하나씩 출력한 뒤 줄바꿈을 수행합니다.

cout<<"첫 번째 행렬:"<<endl;
for(i=0; i<r1; ++i) {
   for(j=0; j<c1; ++j)
   cout<<a[i][j]<<" ";
   cout<<endl;
}
cout<<endl;
cout<<"두 번째 행렬:"<<endl;
for(i=0; i<r2; ++i) {
   for(j=0; j<c2; ++j)
   cout<<b[i][j]<<" ";
   cout<<endl;
}
cout<<endl;

4단계: 행렬 곱셈 수행

먼저 결과를 저장할 product[][] 배열의 모든 원소를 0으로 초기화합니다. 이후 삼중 for 루프를 사용하여 두 행렬의 곱을 계산하는데, 여기서 k 루프는 첫 번째 행렬의 행 원소와 두 번째 행렬의 열 원소를 짝지어 곱한 값을 누적하는 역할을 담당합니다.

for(i=0; i<r1; ++i)
for(j=0; j<c2; ++j) {
   product[i][j] = 0;
}
for(i=0; i<r1; ++i)
for(j=0; j<c2; ++j)
for(k=0; k<c1; ++k) {
   product[i][j]+=a[i][k]*b[k][j];
}

5단계: 곱셈 결과 출력

곱셈이 완료되면 중첩 for 루프를 통해 결과 행렬을 화면에 출력합니다.

cout<<"두 행렬의 곱:"<<endl;
for(i=0; i<r1; ++i) {
   for(j=0; j<c2; ++j)
   cout<<product[i][j]<<" ";
   cout<<endl;
}

마무리

이 프로그램은 세 개의 중첩 루프를 사용하므로 시간 복잡도는 O(n³)입니다. n이 커질수록 연산량이 급격히 증가하므로, 대규모 행렬 연산에는 캐시 최적화나 분할 정복 기반의 스트라센(Strassen) 알고리즘 같은 고급 기법이 활용되기도 합니다. 하지만 행렬 곱셈의 기본 원리를 이해하는 데에는 위와 같은 삼중 루프 구조가 가장 명확하고 효과적인 출발점입니다.