어제 날라간 posfix 계산기를 다시 코딩해봤다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def postfix_calculator(expression):
    operator = ['+''-''*''/''^''%'#'^', '%'는 '*', '/'와 동일한 우선순위를 갖는다.
    operand = ['0''1''2''3''4' ,'5''6' ,'7','8''9'#식을 문자열로 입력받으므로 문자열로 처리함.
    opstack = []
    outstack = []
    calcstack = []
    
    for factor in expression:   #postfix로 변환하는 과정
        if factor in operand:
            outstack.append(factor)
        
        elif factor == '(':
            opstack.append(factor)
        
        elif factor == ')':
            while True:
                x = opstack.pop()
                if x == '(':
                    break
                outstack.append(x)
        
        elif factor in operator:    #operator임을 명시하기 위해 적었음.
            if (factor == ('+' or '-')) and (operator in ['*''/''^''%']):
                 outstack.append(opstack.pop())
            else:
                opstack.append(factor)
                #+와 -만 opstack에서 다른 높은 연산자를 마주쳤을 때 비켜주고, 그 경우가 아니면 들어가면 된다.
    
    for i in range(len(opstack)):
        outstack.append(opstack.pop())  #opstack의 남은 수식들을 위부터 outstack에 append한다.
    #########################여기부터 계산과정###################################
    for factor in outstack:
        if factor in operand:
            calcstack.append(factor)
        
        elif factor in operator:
            if factor == '+':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b+a)
            
            elif factor == '-':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b-a)
            
            elif factor == '*':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b*a)
            
            elif factor == '/':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b/a)
            
            elif factor == '^':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b**a)
            
            elif factor == '%':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b%a)
                
    answer = calcstack[0]
    return outstack, answer
               
expr = input()
outstack, answer = postfix_calculator(expr)
postfix = ' '.join(s for s in outstack)
 
print(f'입력한 식은 "{expr}"입니다.')
print(f'postfix로 변환한 식은 "{postfix}"이고,\n계산된 값은 {answer}입니다.')
cs

잘 돌아가겠구나 싶었는데 문제가 하나 발생했다.

얘가 두 자리수 이상을 인식하지 못 한다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
def postfix_calculator(expression):
    operator = ['+''-''*''/''^''%'#'^', '%'는 '*', '/'와 동일한 우선순위를 갖는다.
    operand = [str(x) for x in range(01001)] #식을 문자열로 입력받으므로 문자열로 처리함.
    opstack = []
    outstack = []
    calcstack = []
        
    for factor in expression:   #postfix로 변환하는 과정
        if factor == '(':
            opstack.append(factor)
        
        elif factor == ')':
            while True:
                x = opstack.pop()
                if x == '(':
                    break
                outstack.append(x)
                
        elif factor not in operator:
            outstack.append(factor)
        
        elif factor in operator:    #그냥 1대1로 연산자를 대응해도 되지만, operator임을 명시하기 위해 적었음.
            if (factor == ('+' or '-')) and (operator in ['*''/''^''%']):
                 outstack.append(opstack.pop())
            else:
                opstack.append(factor)
                #+와 -만 opstack에서 다른 높은 연산자를 마주쳤을 때 비켜주고, 그 경우가 아니면 들어가면 된다.
        
    for i in range(len(opstack)):
        outstack.append(opstack.pop())  #opstack의 남은 수식들을 위부터 outstack에 append한다.
    #########################여기부터 계산과정###################################
    for factor in outstack:
        if factor in operand:
            calcstack.append(factor)
        
        elif factor in operator:
            if factor == '+':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b+a)
            
            elif factor == '-':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b-a)
            
            elif factor == '*':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b*a)
            
            elif factor == '/':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b/a)
            
            elif factor == '^':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b**a)
            
            elif factor == '%':
                a = int(calcstack.pop())
                b = int(calcstack.pop())
                calcstack.append(b%a)
        
    answer = int(calcstack[0])
    return outstack, answer
 
expr = list(input().split(' '))
processed_expr = ' '.join(s for s in expr)
 
try:
    outstack, answer = postfix_calculator(expr)
    postfix = ' '.join(s for s in outstack)
    print(f'입력한 식은 "{processed_expr}"입니다.')
    print(f'postfix로 변환한 식은 "{postfix}"이고,\n계산된 값은 {answer}입니다.')
except:
    print('오류가 발생했습니다! 계산기를 종료합니다.')
cs

// 연산자는 /과 충돌이 일어나서 일단은 제외했다.

 

리스트 컴프리헨션을 이용해서 1부터 10000까지 연산이 가능하게 설정했고,

 

식을 띄어쓰기로 입력하게끔 했다

(기존에 (15*2)+1 == 1 5 * 2 + 1 과 같이 알아봤지만 ( 15 * 2 ) + 1 로 쓰면 15 * 2 + 1로 알아보게끔 함)

 

이외에 예외처리 문구도 넣어봤다.

 

어라라? -27이 나와야 하는데..?

*이 맨 마지막에 가있는게 에러다.

 

성공!


실패!

 

'-'가 '^'를 안 빼줘서 5의 155승이 되어버렸다

 

차근차근 짚어보자.

' - '는 (, )도 아니고 operator이기 때문에 else문으로 들어간다.

위에서는 이미 '^'가 자리하고 있기 때문에 elif문으로 들어간다.

factor == '-' 이기 때문에 전건을 만족한다 + opstack[-1] == '^'이기 때문에 후건도 만족, 따라서 연언문을 만족한다.

그러므로 outstack.append(opstack.pop())과 opstack.append(factor)이 실행이 되어야 하는데..

 

 


해결했다.
elif문에서 괄호를 제대로 쳐주지 않아서 발생한 문제였다.

(factor == '-' or '+') and (opstack[-1] in ['*', '/', '^', '%']) // factor == ('+' or '-') and opstack[-1] in ['*', '/', '^', '%']

둘의 차이는 뭘까?

() and () 꼴로 묶였냐 안 묶였냐인 것 같다.

논리학에서도 교수님이 그렇게 괄호를 중요시하셨는데.. 그새 잊었나보다.

좌항의 경우에는 원하는 논리식이 명확한데, 오른쪽은 그렇지 않다.

조건식을 쓸 때에는 더 주의해서 괄호를 사용해야겠다.


장장 세시간에 걸쳐 완성된 계산기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
def postfix_calculator(expression):
    operator = ['+''-''*''/''^''%'#'^', '%'는 '*', '/'와 동일한 우선순위를 갖는다.
    opstack = []
    outstack = []
    calcstack = []
        
    for factor in expression:   #postfix로 변환하는 과정
        if factor == '(':
            opstack.append(factor)
        
        elif factor == ')':
            while True:
                x = opstack.pop()
                if x == '(':
                    break
                outstack.append(x)
                
        elif factor not in operator:
            outstack.append(factor)
            
        else:
            if len(opstack) == 0:
                opstack.append(factor)    
                    
            elif (factor == '-' or '+'and (opstack[-1in ['*''/''^''%']):
                outstack.append(opstack.pop())
                opstack.append(factor)
                
            else:
                opstack.append(factor)
            
    for i in range(len(opstack)):
        outstack.append(opstack.pop())  #opstack의 남은 수식들을 위부터 outstack에 append한다.
    #########################여기부터 계산과정###################################
    for factor in outstack:
        if factor not in operator:
            calcstack.append(factor)
        
        if factor == '+':
            a = calcstack.pop()
            b = calcstack.pop()
            calcstack.append(int(b)+int(a))
            
        elif factor == '-':
            a = calcstack.pop()
            b = calcstack.pop()
            calcstack.append(int(b)-int(a))
            
        elif factor == '*':
            a = calcstack.pop()
            b = calcstack.pop()
            calcstack.append(int(b)*int(a))
            
        elif factor == '/':
            a = calcstack.pop()
            b = calcstack.pop()
            calcstack.append(int(b)/int(a))
            
        elif factor == '^':
            a = calcstack.pop()
            b = calcstack.pop()
            calcstack.append(int(b)**int(a))
            
        elif factor == '%':
            a = calcstack.pop()
            b = calcstack.pop()
            calcstack.append(int(b)%int(a))
 
    answer = int(calcstack[0])
    return outstack, answer
 
expr = list(input().split(' '))
processed_expr = ' '.join(s for s in expr)
print(f'입력한 식은 "{processed_expr}"입니다.')
 
outstack, answer = postfix_calculator(expr)
postfix = ' '.join(s for s in outstack)
print(f'postfix로 변환한 식은 "{postfix}"이고,\n계산된 값은 {answer}입니다.')
cs

어떻게든 물고 늘어지고 찾으면 고칠 수 있다!

야호!
복사했습니다!