행렬의 곱셈은 어렵다 ㅎㅎㅎ
고등학교 때 제일 못했던 것이 행렬이어서 ㅜㅜㅜ 행렬 정말 싫다(수능 때 수학 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;
}
}
결과
'JAVA > 실습' 카테고리의 다른 글
[java][실습] 006 이차원 배열에서 좌표에 X 찍기 (0) | 2020.07.05 |
---|---|
[java][실습] 005 오름차순, 내림차순으로 배열요소 정렬 (0) | 2020.07.05 |
[java][실습] 004 배열 섞기 (0) | 2020.07.05 |
[java][실습] 003 배열에서 최대값과 최소값 찾기 (0) | 2020.07.05 |
[java][실습] 002 별 찍기(삼각형, 역삼각형, 반삼각형, 육각형) (0) | 2020.07.02 |