parsing math expression in python and solving to find an answer

后端 未结 3 552
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: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'))
    

提交回复
热议问题