행렬의 곱셈은 어렵다 ㅎㅎㅎ

고등학교 때 제일 못했던 것이 행렬이어서 ㅜㅜㅜ 행렬 정말 싫다(수능 때 수학 1문제 틀렸는데 1번 행렬문제였다)

여튼 뭐 이거랑 그거랑은 다르니까. 난 더 이상 행렬 시험을 치지 않으니까..ㅜㅜ

 

참고하기. 행렬의 곱셈

2020/07/05 - [[개발 & 독학]/reference] - [고등수학] 행렬의 곱셈

 

조금 복잡하다.

알고리즘 할 때 이야기 하겠지만

행렬은 결합법칙이 성립하는데 결합하는 방향에 따라 속도가 많이 차이가 난다.

적게 계산할 수 있도록 만들어 줘야 되는데, 그 것은 나중에 포스팅 하게 되면 여기에 연결하도록 하곘다.

또 콘솔에서 입력받아서 자유도를 높이다보니 좀 복잡하다.

찬찬히 설명해도 모르겠으면 댓글 주시길 바란다.

 

1. 클래스 멤버 선언

곱하기 할 배열들을 미리 정의하자.

행렬을 2차원 배열이므로 저런식으로 초기화 해줬다.

Scanner scanner = new Scanner(System.in);

	int [][] a = {{4, 4, 5}, {3, 7, 2}}; // 2, 3
	int [][] b = {{7, 5, 1, 2}, {9, 6, 4, 3}, {4, 2, 1, 6}}; // 3, 4
	int [][] c = {{8, 4}, {5, 7}, {2, 3}, {9, 6}}; // 4, 2
	int [][] d = {{1, 4}, {9, 3}, {7, 6}}; // 3, 2
	
	// a * b , b * c , c * a

 

2. showArray(int[][] a)

배열을 보는 메서드를 정의한다.

void showArray(int[][] a) {
		for(int[] col : a) {
			for(int tmp : col) {
				System.out.print(tmp+" ");
			}
			System.out.println();
		}
		System.out.println();
	}

 

3. findArray(char ch)

콘솔에서 곱셈을 실행할 행렬을 직접 입력 받아서 그 행렬들 끼리 곱셈을 하도록 구현한다.

따라서 입력받은 문자를 내가 가진 행렬로 바꿔야 한다.

입력받은 문자를 매개변수로 하는 메서드이며

각 글자가 일치하는 행렬을 반환한다.

this는 멤버변수를 나타내는 참조변수이다. 이론에 나오니 확인해 보시길

2020/07/02 - [[JAVA]/이론] - [java][이론] 005 클래스와 객체

2020/07/04 - [[JAVA]/이론] - [java][이론] 007 생성자와 변수의 초기화

	int [][] findArray(char ch) {

		int [][] result = null;
		
		if(ch=='a'){
			result = this.a;			
		} else if(ch=='b'){
			result = this.b;			
		} else if(ch=='c'){
			result = this.c;
		} else if(ch=='d'){
			result = this.d;
		}else {
			System.out.println("없는 행렬을 골랐습니다.");
		}
		
		return result;
	}

 

4. chooseArray()

콘솔에서 입력한 문자를 받아서 배열로 만드는 메서드이다.

배열로 받아서 나중에 위의 findArray(char ch) 함수의 매개변수로 각 요소를 넣으면

문자 배열 안에 있는 문자에 맞게 각 배열이 선택될 것이다.

 

일단 이것은 배열을 받을 때 일종의 유효값 검사에 해당한다고 볼 수 있다

멤버변수로 선언한 배열이 a b c d 뿐이므로 그것이 아닌 다른 문자를 넣지 못하도록 한 것이다.

받은 글자들이 abcd중에 있다면 문자열에 추가하고 그렇지 않으면 안된다고 한다.

반복문을 써서 사용자가 원할 때 입력을 멈출 수 있다.

 

다 받은 문자열을 chatAt함수로 배열에 넣어 반환한다.

char[] chooseArray() {
		
		char[] result;
		String choice = "";
		
		while (true) {
			String tmp = scanner.nextLine();
			  
			if(tmp.equals("q")) {
				break;
			} else if(tmp.equals("a") | tmp.equals("b") | tmp.equals("c") | tmp.equals("d")) {
				choice += tmp;
			} else {	
				System.out.println("사용할 수 없는 행렬입니다.");
				continue;
			}
		}
		System.out.println(choice);
		result = new char[choice.length()];

		for(int i = 0; i < result.length; i++) {
			result[i] = choice.charAt(i);
		}
		return result;
	}

 

5. mulArrayDouble(int [][] a, int [][] b)

두 행렬일 때 곱하기 이다.

fot 안의 반복자를 어떻게 사용했는지 잘 보기 바란다.

행렬 포스팅을 참고하면 이해가 쉬울 듯 하다.

포인트는 앞 행렬의 행이 바뀌는 것과 뒷 행렬의 열이 바뀌는 것을 잘 포함 시키는 것이고

또 앞 행렬의 행과 뒷 행렬의 열이 곱해지는데 그 인덱스가 같다는 것이다.

 

또한 앞 행렬의 열과 뒷 행렬의 행의 크기가 같아야 곱할 수 있으므로 조건문으로 검사해줬다.

int[][] mulArrayDouble(int [][] a, int [][] b){
		
		int [][] result = new int[a.length][b[0].length];
		
		if(a[0].length == b.length) {
			for(int h=0;h<a.length;h++)	{ 
				for(int i=0;i<b[h].length;i++) {
					int tmp = 0;
					for(int j=0;j<b.length;j++) {
						tmp += a[h][j]*b[j][i];
					}
					result[h][i] = tmp;
				}
			}
		}else {
			System.out.println("행렬을 곱할 수 없는 순서 입니다. 다시 입력해 주세요.");
		}
		return result;
	}

 

6. mulArrayTriple(int [][] a, int [][] b, int [][] c)

세 행렬이다.

위에서 언급했드시 어떻게 곱하느냐에 따라 속도 차이가 난다.

더 적게 곱할 수 있도록 고안해서

위의 mulArrayDouble(int [][] a, int [][] b)을 이용해 곱해줬다.

다음에는 한 메서드를 제귀호출 할 수 있도록 구현해 보겠다.

int [][] mulArrayTriple(int [][] a, int [][] b, int [][] c){
		int [][] result = new int[a.length][b[0].length];
		
		if(a.length >= c[0].length) {
			result = mulArrayDouble(a,mulArrayDouble(b,c));
		}else {
			result = mulArrayDouble(mulArrayDouble(a,b),c);
		}
		return result;
	}

 

7. showQuestion() 

문제 보는게 길어서 따로 메서드로 뽑았다.

void showQuestion() {
		System.out.println("행렬 a");
		showArray(a);
		
		System.out.println();
		System.out.println("행렬 b");
		showArray(b);	
		
		System.out.println();
		System.out.println("행렬 c");
		showArray(c);
		
		System.out.println();
		System.out.println("행렬 d");
		showArray(d);
		
		System.out.println();
		System.out.println("곱할 행렬을 쓰세요. 완료 : q");
	}
	

 

8. main()

콘솔로 입력받은 문자들을 배열로 만들어서

그 배열의 길이가 얼마냐에 따라 실행하는 곱셈 메서드가 달라진다.

배열 길이가 2 면 mulArrayDouble(int [][] a, int [][] b)메서드를

배열 길이가 3 면 mulArrayTriple(int [][] a, int [][] b, int [][] c)메서드를 호출하며

각 메서드 호출 시 매개변수로 넣는 배열들은

findArray(char ch)에 배열 요소들을 넣어서 구현했다.

public static void main(String[] args) {
		MarrayPrac_matrixMul mm = new MarrayPrac_matrixMul();
				
		question : while(true) {
			
			mm.showQuestion();
			
			char[]  matrixArr = mm.chooseArray();
			
			if(matrixArr.length <= 0) 
				continue;
			
			switch (matrixArr.length) {
			case 1 : 
				System.out.println("곱할 것이 없습니다."); 
				break;
			case 2 : 
				System.err.println("결과 : ");
				mm.showArray(mm.mulArrayDouble(mm.findArray(matrixArr[0]), mm.findArray(matrixArr[1])));
				break;
			case 3 : 
				System.err.println("결과 : ");
				mm.showArray(mm.mulArrayTriple(mm.findArray(matrixArr[0]), mm.findArray(matrixArr[1]), mm.findArray(matrixArr[2])));
				break;	
	
			default:
				break question;
			}

			System.out.println("더 곱하시겠습니까? y/n");

			if(mm.scanner.nextLine().equals("y"))
				continue;
			else if(mm.scanner.nextLine().equals("n")){
				break question;
			} else {
				System.out.println("잘못 누르셨습니다. 다시 선택하세요.");
				continue;
			}
		}	
		mm.scanner.close();		
		return;
	}

 

9. 전체 코드

public class MarrayPrac_matrixMul {
/* 행렬의 곱셈
 * 두 행렬을 곱한 결과를 출력
 * 
 * 행렬의 곱셈은 앞 행렬의 열과 뒤 행렬의 헹의 크기가 같아야 가능
 * m(a,b) n(b,r) 
 * 곱할 행렬이 많을 경우 행렬을 곱하는 순서(결합법칙)에 따라 속도가 달라지므로 
 * 가능한 행렬 크기가 작은 방향으로 곱하게 해야 함
 * 셋 중 가장 큰 행과 열의 크기가 뭔지 찾아보자
 * 
 */

	Scanner scanner = new Scanner(System.in);

	int [][] a = {{4, 4, 5}, {3, 7, 2}}; // 2, 3
	int [][] b = {{7, 5, 1, 2}, {9, 6, 4, 3}, {4, 2, 1, 6}}; // 3, 4
	int [][] c = {{8, 4}, {5, 7}, {2, 3}, {9, 6}}; // 4, 2
	int [][] d = {{1, 4}, {9, 3}, {7, 6}}; // 3, 2
	
	// a * b , b * c , c * a
	
	int[][] mulArrayDouble(int [][] a, int [][] b){
		
		int [][] result = new int[a.length][b[0].length];
		
		if(a[0].length == b.length) {
			for(int h=0;h<a.length;h++)	{ 
				for(int i=0;i<b[h].length;i++) {
					int tmp = 0;
					for(int j=0;j<b.length;j++) {
						tmp += a[h][j]*b[j][i];
					}
					result[h][i] = tmp;
				}
			}
		}else {
			System.out.println("행렬을 곱할 수 없는 순서 입니다. 다시 입력해 주세요.");
		}
		return result;
	}
	
	int [][] mulArrayTriple(int [][] a, int [][] b, int [][] c){
		int [][] result = new int[a.length][b[0].length];
		
		if(a.length >= c[0].length) {
			result = mulArrayDouble(a,mulArrayDouble(b,c));
		}else {
			result = mulArrayDouble(mulArrayDouble(a,b),c);
		}
		return result;
	}
	
	int [][] findArray(char ch) {

		int [][] result = null;
		
		if(ch=='a'){
			result = this.a;			
		} else if(ch=='b'){
			result = this.b;			
		} else if(ch=='c'){
			result = this.c;
		} else if(ch=='d'){
			result = this.d;
		}else {
			System.out.println("없는 행렬을 골랐습니다.");
		}
		
		return result;
	}
	
	void showArray(int[][] a) {
		for(int[] col : a) {
			for(int tmp : col) {
				System.out.print(tmp+" ");
			}
			System.out.println();
		}
		System.out.println();
	}
	
	void showQuestion() {
		System.out.println("행렬 a");
		showArray(a);
		
		System.out.println();
		System.out.println("행렬 b");
		showArray(b);	
		
		System.out.println();
		System.out.println("행렬 c");
		showArray(c);
		
		System.out.println();
		System.out.println("행렬 d");
		showArray(d);
		
		System.out.println();
		System.out.println("곱할 행렬을 쓰세요. 완료 : q");
	}
	
	char[] chooseArray() {
		
		char[] result;
		String choice = "";
		
		while (true) {
			String tmp = scanner.nextLine();
			  
			if(tmp.equals("q")) {
				break;
			} else if(tmp.equals("a") | tmp.equals("b") | tmp.equals("c") | tmp.equals("d")) {
				choice += tmp;
			} else {	
				System.out.println("사용할 수 없는 행렬입니다.");
				continue;
			}
		}
		System.out.println(choice);
		result = new char[choice.length()];

		for(int i = 0; i < result.length; i++) {
			result[i] = choice.charAt(i);
		}
		return result;
	}
	
	public static void main(String[] args) {
		MarrayPrac_matrixMul mm = new MarrayPrac_matrixMul();
				
		question : while(true) {
			
			mm.showQuestion();
			
			char[]  matrixArr = mm.chooseArray();
			
			if(matrixArr.length <= 0) 
				continue;
			
			switch (matrixArr.length) {
			case 1 : 
				System.out.println("곱할 것이 없습니다."); 
				break;
			case 2 : 
				System.err.println("결과 : ");
				mm.showArray(mm.mulArrayDouble(mm.findArray(matrixArr[0]), mm.findArray(matrixArr[1])));
				break;
			case 3 : 
				System.err.println("결과 : ");
				mm.showArray(mm.mulArrayTriple(mm.findArray(matrixArr[0]), mm.findArray(matrixArr[1]), mm.findArray(matrixArr[2])));
				break;	
	
			default:
				break question;
			}

			System.out.println("더 곱하시겠습니까? y/n");

			if(mm.scanner.nextLine().equals("y"))
				continue;
			else if(mm.scanner.nextLine().equals("n")){
				break question;
			} else {
				System.out.println("잘못 누르셨습니다. 다시 선택하세요.");
				continue;
			}
		}	
		mm.scanner.close();		
		return;
	}
}

 

결과

 

 

+ Recent posts