Dlise
시원한 냉장고
Dlise
전체 방문자
오늘
어제
  • 시원한 냉장고 (132)
    • Java (31)
      • Java (26)
      • Spring (5)
    • Algorithm & PS (25)
      • Algorithm (14)
      • Problem Solving (11)
    • Network (12)
    • Database (2)
    • Data Structure (4)
    • OOP & CleanCode (5)
    • Web (0)
    • Git (2)
    • AI (2)
    • Project (1)
      • Discord Bot (1)
    • Error (19)
    • Tools (5)
    • 수학 (5)
      • 확률과 통계(기초) (5)
    • 컴퓨터 구조 (3)
    • 활동 (16)
      • 행사 & 여행 (6)
      • 자격증 (4)
      • 회고 (6)
      • 기타 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 열혈강의자료구조
  • CleanCode
  • 중위 표기법
  • 가장쉬운알고리즘책
  • java
  • spring security in action second edition
  • 네트워크
  • 백준
  • 후위 표기법
  • 통계학

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Dlise

시원한 냉장고

Java/Java

Java - 중위 - 후위 표기법 변환 & 후위 표기법 계산

2023. 8. 24. 16:15

간단하게 계산기를 만들던 중 식을 후위로 변환하고 계산할 필요가 생겨 이를 정리해보고자 한다.

 

간단하게 만들어본 계산기인데 연산자 우선순위에 맞게 계산하려고 하니 막히는 부분이 많았다.

그래서 검색을 한 결과 식을 후위 표기법으로 바꾼 후 계산하는 것이 일반적이라는 것을 알았다.

 

중위 - 후위 변환

먼저 중위 표기법인 위 식을 후위 표기법으로 변환해 보자.

위 식 "22 + 4 * 36 - 7"을 이진트리 형태로 보면 아래와 같다.

중위 표기법은 22 + 4 * 36 - 7

후위 표기법은 22 4 36 * + 7 - 이다.

 

이제 변환하는 코드를 짜보자.

 

변환을 위해 HashMap, Stack, ArrayList를 활용했다.

HashMap은 굳이 써야 할까 고민했지만 함수를 공부한다는 느낌으로 사용했다.

String getResult(String str) {
	//식이 담겨있는 str을 " "로 나눠서 strArr에 담음
	String[] strArr = str.split(" ");
	
	//연산자 우선순위를 위한 HashMap
	HashMap<String, Integer> pri = new HashMap<>();
	pri.put("+", 0);
	pri.put("-", 0);
	pri.put("*", 1);
	pri.put("/", 1);
	pri.put("%", 1);

	//우선순위에 맞게 담기 위한 stack
	Stack<String> stack = new Stack<>();
    
	//출력 결과를 담기 위한 ArrayList
	ArrayList<String> reverseStrArr = new ArrayList<>();
    
	//strArr을 순서대로 접근
	for(String s : strArr) {
		//s가 연산자인 경우
		if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/") || s.equals("%")) {
			//스택이 비어있는 경우 - 바로 push
			if(stack.isEmpty())
				stack.push(s);
                
			//스택이 비어있지 않은 경우
			else { 
				//스택에 담겨있는 연산자보다 s가 우선순위가 더 높으면 바로 push
				if(pri.get(stack.peek()) < pri.get(s)) 
					stack.push(s);
                    
				//스택에 담겨있는 연산자 우선순위가 더 높으면 pop한 후 push
				else {
					while(true) {
						if(stack.isEmpty() || pri.get(stack.peek()) < pri.get(s)) {
							stack.push(s);
							break;
						}
						reverseStrArr.add(stack.pop());
					}
				}
			}
		} 
		//s가 피연산자인 경우 바로 ArrayList에 담음
		else {
			reverseStrArr.add(s);
		}
	}
    
	//위 작업이 끝난 후 스택에 남아있는 연산자를 모두 ArrayList에 담음
	while(!stack.isEmpty()) {
		reverseStrArr.add(stack.pop());
	}
}

 

과정을 설명하자면 다음과 같다.

1. 식을 나눈다.
2. 연산자 우선순위를 정한다.
3 - 1. 문자열이 연산자인 경우
    - 스택이 비어있는 경우 바로 push
    - 스택이 비어있지 않은 경우 연산자 우선순위를 확인한 후 pop or push
3 - 2. 문자열이 피연산자인 경우 리스트에 바로 add
4. 스택에 남은 문자열을 리스트에 add

 

후위 표기법 계산

이제 후위 표기법으로 바꾼 식을 계산해 보자.

코드가 어렵지 않으므로 바로 보면 다음과 같다.

for(String s : reverseStrArr) {
	if(!(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/") || s.equals("%")))
		stack.add(s);
	else {
		BigDecimal num2 = new BigDecimal(stack.pop());
		BigDecimal num1 = new BigDecimal(stack.pop());
		switch(s) {
			case "+":
				stack.push(num1.add(num2).toString());
				break;
			case "-":
				stack.push(num1.subtract(num2).toString());
				break;
			case "*":
				stack.push(num1.multiply(num2).toString());
				break;
			case "/":
				stack.push(num1.divide(num2, 4, RoundingMode.HALF_UP).toString());
				break;
			default:
				stack.push(num1.remainder(num2).toString());
				break;
		}
	}
}
return stack.pop();

1. 피연산자는 stack에 담는다.

2. 연산자가 나오면 stack에서 피연산자 2개를 pop해 계산한다.

3. 결과를 다시 stack에 push 한다.

 

 

계산 범위를 최대한 늘리고 소수도 계산하기 위해서 BigDecimal을 활용했다.

후위 표기법으로 바꿨기 때문에 매우 간단하게 계산이 가능하다.

모든 계산을 마치면 stack엔 계산 결과 하나만 남아있으므로 pop해 return한다.

'Java > Java' 카테고리의 다른 글

Java - Thread에서 while문 안의 if문이 동작하지 않는 이유  (0) 2023.09.01
Java - sort() (Comparator & Comparable)  (0) 2023.08.31
Java - Java 클래스, 객체, 인스턴스  (0) 2023.07.16
Java - Java 배열  (0) 2023.02.10
Java - Java 조건문과 반복문  (0) 2023.02.10
    'Java/Java' 카테고리의 다른 글
    • Java - Thread에서 while문 안의 if문이 동작하지 않는 이유
    • Java - sort() (Comparator & Comparable)
    • Java - Java 클래스, 객체, 인스턴스
    • Java - Java 배열
    Dlise
    Dlise

    티스토리툴바