parsing math expression in python and solving to f

2019-01-20 06:30发布

I am quite new to programming. This is in relation to python. So the idea is to take an expression such as 3/5 or, at most, 3/5*2(at most two operators, note that the operators can be any of +,-,/,*) and solve it. White space can exist anywhere within the expression.

The user enters the expression, say 3/5, and the program needs to solve the expression and display the answers. What I have tried is below. Note, I only have attempted the first part, once I can properly split the original expression that the user enters(which would be a string), creating functions would be the easy part:

expres= str(input("something:"))

ssplit= hit.partition("/")
onec= int((ssplit[0].lstrip()).rstrip())
twoc= (ssplit[1].lstrip()).rstrip()
threec= int((huns[2].lstrip()).rstrip())


print(onec,"...",twoc,"...",threec) #just a debug test print

So above, I can take an expression like 3/5 and split it into three separate strings:3 , /, and 5. I can also remove all whitespace before and after the operators/operands. I am having problems with splitting expressions like 4/5+6, Because I can't put code in for ssplit[3] or ssplit[4] and then enter an expression like 3/5, because it won't be defined. Basically I needed you help to find out how to split an expression like 3/4-6,etc. I also need help with the line "ssplit= hit.partition("/")" so that it will look at the entered expression and work with +,-, and * as well. Any and all help is appreciated. Also if my code above looks nasty and inefficient please give me criticism. Thanks!

Note I can't, and wouldn't want to use eval. Order of operations is required. I cant use complicated commands. I need to keep it simple, the most I can use is string libraries, converting between strings/integers/floats etc. and if,and,etc. statements. I can also use functions.

3条回答
地球回转人心会变
2楼-- · 2019-01-20 07:10

Use the shlex and StringIO Python module. In Python 2.3+:

>>> from StringIO import StringIO
>>> import shlex
>>> input = StringIO('3/4+5')
>>> list(shlex.shlex(input))
['3', '/', '4', '+', '5']
查看更多
倾城 Initia
3楼-- · 2019-01-20 07:24

If I wasn't going to rely on external libraries, I'd do it something like this:

def parse(x):
    operators = set('+-*/')
    op_out = []    #This holds the operators that are found in the string (left to right)
    num_out = []   #this holds the non-operators that are found in the string (left to right)
    buff = []
    for c in x:  #examine 1 character at a time
        if c in operators:  
            #found an operator.  Everything we've accumulated in `buff` is 
            #a single "number". Join it together and put it in `num_out`.
            num_out.append(''.join(buff))
            buff = []
            op_out.append(c)
        else:
            #not an operator.  Just accumulate this character in buff.
            buff.append(c)
    num_out.append(''.join(buff))
    return num_out,op_out

print parse('3/2*15')

It's not the most elegant, but it gets you the pieces in a reasonable data structure (as far as I'm concerned anyway)

Now code to actually parse and evaluate the numbers -- This will do everything in floating point, but would be easy enough to change ...

import operator
def my_eval(nums,ops):

    nums = list(nums)
    ops = list(ops)
    operator_order = ('*/','+-')  #precedence from left to right.  operators at same index have same precendece.
                                  #map operators to functions.
    op_dict = {'*':operator.mul,
               '/':operator.div,
               '+':operator.add,
               '-':operator.sub}
    Value = None
    for op in operator_order:                   #Loop over precedence levels
        while any(o in ops for o in op):        #Operator with this precedence level exists
            idx,oo = next((i,o) for i,o in enumerate(ops) if o in op) #Next operator with this precedence         
            ops.pop(idx)                        #remove this operator from the operator list
            values = map(float,nums[idx:idx+2]) #here I just assume float for everything
            value = op_dict[oo](*values)
            nums[idx:idx+2] = [value]           #clear out those indices

    return nums[0]

print my_eval(*parse('3/2*15'))
查看更多
乱世女痞
4楼-- · 2019-01-20 07:29

That's not really the way to parse an expression, you should look more into lexers and parsers, something like PLY or pyparsing. However, if you just want to evaluate the expression you could use eval(expr). Note that eval will execute any code you feed it, so it's not really safe.

Edit There's an example here for using pyparsing, that should get you started:

pyparsing example

查看更多
登录 后发表回答