【问题标题】:parsing math expression in python and solving to find an answer解析python中的数学表达式并求解以找到答案
【发布时间】:2012-10-24 18:57:42
【问题描述】:

我对编程很陌生。这与python有关。所以想法是取一个表达式,例如 3/5 或最多 3/5*2(最多两个运算符,注意运算符可以是 +、-、/、* 中的任何一个)并解决它。空格可以存在于表达式中的任何位置。

用户输入表达式,比如 3/5,程序需要求解表达式并显示答案。我尝试过的如下。注意,我只尝试了第一部分,一旦我可以正确拆分用户输入的原始表达式(这将是一个字符串),创建函数将是简单的部分:

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

因此,在上面,我可以将 3/5 之类的表达式拆分为三个单独的字符串:3、/ 和 5。我还可以删除运算符/操作数前后的所有空格。我在拆分 4/5+6 之类的表达式时遇到问题,因为我无法为 ssplit[3] 或 ssplit[4] 输入代码,然后输入 3/5 之类的表达式,因为它不会被定义。基本上我需要你帮助找出如何拆分像 3/4-6 等的表达式。我还需要“ssplit= hit.partition("/")”行的帮助,以便它可以查看输入的表达式并使用 +、- 和 *。任何和所有的帮助表示赞赏。另外,如果我上面的代码看起来很糟糕而且效率低下,请给我批评。谢谢!

注意我不能,也不想使用 eval。 操作顺序是必需的。 我不能使用复杂的命令。我需要保持简单,我最多可以使用字符串库,在字符串/整数/浮点数等以及 if、and 等之间进行转换。陈述。我也可以使用函数。

【问题讨论】:

  • 你不应该需要str(input(...))。如果您使用的是 py3k,则输出已经是一个字符串。如果你使用的是 py2k,那么你应该使用raw_input
  • eval(raw_input()) 怎么样:P
  • @JohnVinyard 我会将其发布为答案...
  • @user1716168 -- 你需要担心操作的顺序吗?例如,你希望从2+3*2 中得到什么——如果你从左到右解析,你会得到 12,如果你使用操作顺序解析,你会得到 8 ...
  • @abought -- 是的。你可以做一些事情让它变得更好。您可以通过全局和本地字典来限制 eval 可以做什么。即使这样,也有一些鲜为人知的问题,但是如果您小心并知道自己在做什么,则可以解决它们。也就是说,如果您不确定自己在做什么,最好避免这样做。

标签: python string parsing split expression


【解决方案1】:

如果我不打算依赖外部库,我会这样做:

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')

这不是最优雅的,但它可以让你得到一个合理的数据结构(就我而言无论如何)

现在编写代码来实际解析和评估数字——这将在浮点中完成所有操作,但很容易更改......

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'))

【讨论】:

  • 可能应该在某处添加.strip() 以跳过空格。此外,不幸的是,这不尊重 OP 想要的操作顺序。
  • @nneonneo -- 不过这并不重要。 intfloat(将在下一阶段使用)都将接受数字周围的空格...
  • 你能为你的 opout numout 和 buff 命令添加一些文档吗?一旦我进入 if 语句,我就会迷失方向。
  • @user1716168 -- 如果我有帮助,您可以使用 buff = '' 而不是 buff = []buff += c 而不是 buff.append(c),然后您可以将 buff 放入 num_out而不是''.join(buff)。 (但使用列表可能更有效)
  • @mgilson 它清理了很多,但是你能不能多补充一点关于buff,它是什么,以及它是如何通过函数改变的?
【解决方案2】:

这不是解析表达式的真正方法,您应该更多地研究词法分析器和解析器,例如PLYpyparsing。但是,如果您只想评估表达式,您可以使用eval(expr)。请注意,eval 将执行您提供给它的任何代码,因此它并不安全。

编辑 这里有一个使用 pyparsing 的示例,应该可以帮助您入门:

pyparsing example

【讨论】:

  • eval不能用,我去看看ply,如果代码太高级我就用不上了。
  • 那你应该从pyparsing开始,我觉得开始比较容易。
  • 我检查了这个例子,它对我的​​需求来说太复杂了,因此我不能使用它。如果我不使用外部库会更好。
  • 如果您能提供一个您正在尝试处理的实际数据的示例,以及有关特定应用程序的更多信息,那将非常有帮助。这可能使具有相关领域专业知识的人能够根据您的确切问题提供信息和资源。
  • Pyparsing 网站已死
【解决方案3】:

使用shlexStringIO Python 模块。在 Python 2.3+ 中:

>>> from StringIO import StringIO
>>> import shlex
>>> input = StringIO('3/4+5')
>>> list(shlex.shlex(input))
['3', '/', '4', '+', '5']

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多