简体   繁体   中英

Calculator with mathematical parsing error in python

Code:

import re
num=['0','1','2','3','4','5','6','7','8','9']
opr=['+','-','%','/','*','^']
length=0
#tokens,operators,numbers=[],[],[]
def greater_precedence(op1,op2):
    precedence={'+':0,'-':1,'*':2,'/':3}
    return precedence[op1]>precedence[op2]
def peek(stack):
    return stack[-1] if stack else None
def solve(operator,number):
    print('OP1: ',operator,' ','NP1: ',number)
    v=0
    operator.reverse()
    for i,j in enumerate(operator):
        if j=='+':
            num1=number.pop()
            num2=number.pop()
            v=num1+num2
            operator.remove(j)
        if j=='-':
            num1=number.pop()
            num2=number.pop()
            v=num2-num1
            operator.remove(j)
        if j=='*':
            num1=number.pop()
            num2=number.pop()
            v=num1*num2
            operator.remove(j)
        if j=='/':
            num1=number.pop()
            num2=number.pop()
            v=num2/num1
            operator.remove(j)
    operator.reverse()
    number.append(v)
def bracket_op(operator,number,holder):
    #print('Operation: ',exp)
    #print('Operation 1: ',exp_1)
    print('Operators: ',operator,' ','Numbers: ',number)
    v=0
    lth=len(number)
    top=peek(operator)
    operator.reverse()
    print('Length: ',lth)
    print('OP2: ',operator)
    for i,j in enumerate(operator):
        if j=='+' and top=='+':
            num1=number.pop()
            num2=number.pop()
            v=num2+num1
            operator.remove(j)
    #for i,j in enumerate(operator):
        if j=='-' and top=='-':
            num1=number.pop()
            print('S: ',number)
            num2=number.pop()
            v=num1-num2
            operator.remove(j)
    #for i,j in enumerate(operator):
        if j=='*'and top =='*':
            num1=number.pop()
            print('M: ',number)
            num2=number.pop()
            v=num1*num2
            operator.remove(j)
    #for i,j in enumerate(operator):
        if j=='/'and top =='/':
            num1=number.pop()
            print('D: ',number)
            num2=number.pop()
            v=num2/num1
            operator.remove(j)
    operator.reverse()
    
    
    #print('Operators 1: ',operators,' ','Numbers 1: ',numbers)
    print('holder: ',holder)
    number.insert(holder,v)
    print(number)
        

def evaluate(exp):
    tokens=re.findall('[-]|[(,),+,*,^,%,/]|\d+',exp)
    print('Tokens: ',tokens)
    bracket=False
    holder,value=0,0
    operator,number,brackets=[],[],[]
    for token in tokens:
        if token=='(':
            holder=tokens.index(token)
            operator.append(token)
        elif token==')':
            holder=operator.index('(')
            top=peek(operator)
            while top is not None and top is not '(':
                bracket_op(operator,number,holder)
                top=peek(operator)
            operator.pop()
        else:
            if token in num:
                number.append(float(token))
            else:
                top=peek(operator)
                while top is not None and top is not '(' and greater_precedence(top,token):
                    solve(operator,number)
                    top=peek(operator)
                operator.append(token)
    while peek(operator) is not None:
         solve(operator,number)
            
            
    print('Operators: ',operator,'','Numbers: ',number)
    return number
        

        
def main():
    exp=input("Enter: ")
    print("Answer: {0}".format(evaluate(exp)))
if __name__=='__main__':
    main()

Output:

Correct Output:

Enter: (2+2)*(2+2)
Tokens:  ['(', '2', '+', '2', ')', '*', '(', '2', '+', '2', ')']
Operators:  ['(', '+']   Numbers:  [2.0, 2.0]
Length:  2
OP2:  ['+', '(']
holder:  0
[4.0]
Operators:  ['*', '(', '+']   Numbers:  [4.0, 2.0, 2.0]
Length:  3
OP2:  ['+', '(', '*']
holder:  1
[4.0, 4.0]
OP1:  ['*']   NP1:  [4.0, 4.0]
Operators:  []  Numbers:  [16.0]
Answer: [16.0]

Error Output:

Enter: (2+2)+(2+2)
Tokens:  ['(', '2', '+', '2', ')', '+', '(', '2', '+', '2', ')']
Operators:  ['(', '+']   Numbers:  [2.0, 2.0]
Length:  2
OP2:  ['+', '(']
holder:  0
[4.0]
Operators:  ['+', '(', '+']   Numbers:  [4.0, 2.0, 2.0]
Length:  3
OP2:  ['+', '(', '+']
Traceback (most recent call last):
File "F:\TYBScIT\Sem V\Advanced_Calculator_3.py", line 123, in <module>
   main()
File "F:\TYBScIT\Sem V\Advanced_Calculator_3.py", line 121, in main
   print("Answer: {0}".format(evaluate(exp)))
File "F:\TYBScIT\Sem V\Advanced_Calculator_3.py", line 98, in evaluate
   bracket_op(operator,number,holder)
File "F:\TYBScIT\Sem V\Advanced_Calculator_3.py", line 51, in bracket_op
   num2=number.pop()
IndexError: pop from empty list

Don't know why I get this Error It works fine with correct output and wrong when I replace '*' with '+' . It works fine without any brackets ie '(' and ')' . Its main aim is to follow BODMAS rule ie

(B: Brackets,O:Exponential,D:Division,M:Multiplication,A:Addition,S:Subtraction) . I have worked far till only with Brackets,Addition,*,-,/ . Does not work with all other maths work related to +,-,/,* with some extend supporting ( ) (2+2)+(2+2)

Correct Back-end Code for BODMAS rule which works correctly by me. In Python 3.8.3 Shell. For Calculating mathematical string using parsing method

#Note:

It works only for 0-9 numbers.It does not work for any float numbers. While float number work is still under work

#Code

import re
num=['0','1','2','3','4','5','6','7','8','9','.']
opr=['+','-','%','/','*','^']
length=0
def greater_precedence(op1,op2):
precedence={'+':0,'-':1,'*':2,'/':3,'^':4}
return precedence[op1]>precedence[op2]
def peek(stack):
    return stack[-1] if stack else None
def solve(operator,number):
    v=0
    operator.reverse()
    for i,j in enumerate(operator):
        if j=='+':
            num1=number.pop()
            num2=number.pop()
            v=num1+num2
            operator.remove(j)
        if j=='-':
            num1=number.pop()
            num2=number.pop()
            v=float(num2-num1)
            operator.remove(j)
        if j=='*':
            num1=number.pop()
            num2=number.pop()
            v=num1*num2
            operator.remove(j)
        if j=='/':
            num1=number.pop()
            num2=number.pop()
            v=num2/num1
            operator.remove(j)
        if j=='^':
            num1=number.pop()
            num2=number.pop()
            v=num2**num1
            operator.remove(j)
operator.reverse()
number.append(v)
def bracket_op(operator,number):
    v=0
    lth=len(number)
    top=peek(operator)
    operator.reverse()
    number.reverse()
    for i,j in enumerate(operator):
        if j=='+' and top=='+':
            number[0]=number[0]+number[0+1]
            number.remove(number[0+1])
            operator.remove(j)
            top=' '
        if j=='-' and top=='-':
            number[0]=number[0+1]-number[0]
            number.remove(number[0+1])
            operator.remove(j)
            top=' '
        if j=='*'and top =='*':
            number[0]=float(number[0]*number[0+1])
            number.remove(number[0+1])
            operator.remove(j)
            top=' '
        if j=='/'and top =='/':
            number[0]=number[0+1]/number[0]
            number.remove(number[0+1])
            operator.remove(j)
            top=' '
        if j=='^' and top=='^':
            number[0]=number[0+1]**number[0]
            number.remove(number[0+1])
            operator.remove(j)
            top=' '
    operator.reverse()
    number.reverse() 


def evaluate(exp):
    tokens=re.findall('[-]|[(,),+,*,^,%,/]|\d+',exp)
    bracket=False
    holder,value=0,0
    operator,number,brackets=[],[],[]
    for token in tokens:
    if token=='(':
        operator.append(token)
    elif token==')':
        top=peek(operator)
        while top != None and top != '(':
            bracket_op(operator,number)
            top=peek(operator)
        operator.pop()
    else:
        if token in num:
            number.append(float(token))
        else:
            top=peek(operator)
            while top != None and top != '(' and greater_precedence(top,token):
                solve(operator,number)
                top=peek(operator)
            operator.append(token)
while peek(operator) is not None:
     solve(operator,number)
value=number.pop()
return value
        

        
def main():
    exp=input("Enter: ")
    print("Answer: {0}".format(evaluate(exp)))
if __name__=='__main__':
    main()

#Note:

Square root wont work as it need UI

If any error are occured while executing this code plzz comment down below

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM