parsing math expression in python and solving to find an answer

后端 未结 3 551
Happy的楠姐
Happy的楠姐 2020-12-10 10:07

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 operat

相关标签:
3条回答
  • 2020-12-10 10:35

    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']
    
    0 讨论(0)
  • 2020-12-10 10:39

    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'))
    
    0 讨论(0)
  • 2020-12-10 10:39

    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

    0 讨论(0)
提交回复
热议问题