Home > Mobile >  giving precedence to arithmetic operators in python3
giving precedence to arithmetic operators in python3

Time:12-04

I am implementing a simple arithmetic calculation on a server which includes add, sub, mul and Div, for the simplicity purposes no other operations are being done and also no parentheses "()" to change the precedence. The input I will have for the client is something like "1-2.1 3.6*5 10/2"(no dot product, 2.1 or 3.6 is a floating number). I have created a function to send the operands and operators but at a time I can send udp message of 1 computation in the format of (num1,op,num2)

import struct
import socket
ip = "127.0.0.1"
port = 11200
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) #creating socket
print("Do Ctrl c to exit the program !!")

def sendRecv( num1, op, num2):
  #sending udp message with num1,op and num
  #receiving udp message with the result as res
  res = s.recieve()
  return res

sendRecv(in1, in_op, in2)

I was able to split the operators and operands using the regular split and separated them like

str = ['1', '-', '2.1', ' ', '3.6', '*', '5', ' ', '10', '/', '2']

since the multiplication and the division takes precedence over addition and subtraction (3.6, *, 5) should be sent first followed by the division, I am trying to write a while loop with while(len(str>0)), I am trying to understand how I can send multiplication first, store the intermediate result in the list itself and do a recurring function till all the computations are sent through message. I am not allowed to perform ny operation on client side, I can only send values to "SendRecv()". Any suggestions or ideas on how to proceed will be helpful.

Thanks in advance

CodePudding user response:

Recursively split the expression according to operator precedence:

def do_calc(num1, op, num2):
    # Stub to represent the server call that performs one operation.
    # Note that actually using eval() in your backend is REALLY BAD.
    expr = f"{num1} {op} {num2}" 
    res = str(eval(expr))
    print(expr, "=", res)
    return res

def calc_loop(tokens):
    if len(tokens) == 1:
        return tokens[0]
    if len(tokens) == 3:
        return do_calc(*tokens)
    for ops in "- ", "/*":
        if any(op in tokens for op in ops):
            op_idx = max(tokens.index(op) for op in ops if op in tokens)
            return calc_loop([
                calc_loop(tokens[:op_idx]),
                tokens[op_idx],
                calc_loop(tokens[op_idx 1:]),
            ])

expr = ['1', '-', '2.1', ' ', '3.6', '*', '5', ' ', '10', '/', '2']
print(' '.join(expr), '=', calc_loop(expr))

prints:

1 - 2.1 = -1.1
3.6 * 5 = 18.0
10 / 2 = 5.0
18.0   5.0 = 23.0
-1.1   23.0 = 21.9
1 - 2.1   3.6 * 5   10 / 2 = 21.9

CodePudding user response:

Arrange to process only specific operands in a given pass. Make multiple passes, each with different sets of operators. Splice in the answers as they happen.

def doWork(lst, ops):
    lst = list(lst)
    idx = 0
    while idx < len(lst):
        if lst[i] in ops:
            lst[idx-1:idx 2] = sendRecv(*lst[idx-1:idx 2])
        else:
            idx  = 1
    return lst

results = doWork(str, '*/')
results = doWork(results, ' -')
results = results[0]

CodePudding user response:

A typical use case for the classic shunting yard algorithm :

# simulate the conversation with the server
def sendRecv(v1, op, v2):
    res = eval(f'{v1} {op} {v2}')
    return res

# operators and their precedences
ops = { '*': 2, '/': 2, ' ': 1, '-': 1,}

# evaluate a stream of tokens
def evaluate(tokens):
    vstack = []
    ostack = []

    for tok in tokens:
        if tok in ops:
            if ostack and ops[ostack[-1]] >= ops[tok]:
                v2 = vstack.pop()
                v1 = vstack.pop()
                op = ostack.pop()
                vstack.append(sendRecv(v1, op, v2))
            ostack.append(tok)
        else:
            vstack.append(tok)

    while ostack:
        v2 = vstack.pop()
        v1 = vstack.pop()
        op = ostack.pop()
        vstack.append(sendRecv(v1, op, v2))

    return vstack.pop()
    
# test

s = '3   4 * 2   3 / 5   6'

print(eval(s))
print(evaluate(s.split()))
  • Related