[英]giving precedence to arithmetic operators in python3
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.我正在服务器上实现一个简单的算术计算,其中包括 add、sub、mul 和 Div,为了简单起见,没有执行其他操作,也没有括号“()”来更改优先级。 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).我将为客户提供的输入类似于“1-2.1+3.6*5+10/2”(没有点积,2.1 或 3.6 是一个浮点数)。 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)我创建了一个 function 来发送操作数和运算符,但一次我可以发送 udp 1 次计算的消息,格式为 (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'] 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.因为乘法和除法优先于加法和减法 (3.6, *, 5) 应该先发送然后是除法,我正在尝试用 while(len(str>0)) 编写一个 while 循环,我正在尝试要了解我如何首先发送乘法,将中间结果存储在列表本身中并重复执行 function 直到所有计算都通过消息发送。 I am not allowed to perform ny operation on client side, I can only send values to "SendRecv()".我不允许在客户端执行任何操作,我只能将值发送到“SendRecv()”。 Any suggestions or ideas on how to proceed will be helpful.关于如何进行的任何建议或想法都会有所帮助。
Thanks in advance提前致谢
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
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]
A typical use case for the classic shunting yard algorithm :经典调车场算法的典型用例:
# operators and their precedences
ops = { '*': 2, '/': 2, '+': 1, '-': 1,}
# evaluate a stream of tokens
def evaluate(tokens):
vstack = []
ostack = []
def step():
v2 = vstack.pop()
v1 = vstack.pop()
op = ostack.pop()
vstack.append(sendRecv(v1, op, v2))
for tok in tokens:
if tok in ops:
if ostack and ops[ostack[-1]] >= ops[tok]:
step()
ostack.append(tok)
else:
vstack.append(tok)
while ostack:
step()
return vstack.pop()
# simulate the conversation with the server
def sendRecv(v1, op, v2):
res = eval(f'{v1} {op} {v2}')
return res
s = '3 + 4 * 2 + 3 / 5 + 6'
print(eval(s))
print(evaluate(s.split()))
Thank you all for different ideas, I have done my own implementation and tried to keep it very simple.谢谢大家提出不同的想法,我已经完成了自己的实现,并尽量保持简单。 I am not sure if the performance implication is bad on this one, please let me know:-)我不确定这对性能的影响是否不好,请告诉我:-)
def calc_buf(arr, operator):
i = 0
while (len(arr) > i):
if (arr[i] == operator):
calc = sendRecv(arr[i - 1], arr[i], arr[i + 1])
global arth_result
arth_result=calc
arr[i - 1] = calc
del arr[i]
del arr[i]
break
i += 1
return arr
arr =['1', '-', '2.1', '+', '3.6', '*', '5', '+', '10', '/', '2']
i = 0
while (count > i):
i = i + 1
if '/' in arr:
calc_buf(arr, '/')
elif "*" in arr:
calc_buf(arr, '*')
elif "-" in arr:
calc_buf(arr, '-')
elif "+" in arr:
calc_buf(arr, '+')
#print("actual evaluation:",eval(arth)) #for comparing the computation from server
print("result=", arth_result)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.