【问题标题】:Creating a function that takes an equation given as a string and computes it [duplicate]创建一个函数,该函数将给定的方程作为字符串并计算它[重复]
【发布时间】:2014-09-30 21:03:32
【问题描述】:

作为作业的一部分,我正在创建一个接收字符串的函数,该字符串是一个方程。这是一个例子:48+6x6/3=6x8-9x2。计算函数采用等号的一侧并对其进行评估。我不太关心拆分方程。我相信我可以用s[:s.find("=")] 分割它。

我的主要问题是计算函数本身。我会发布到目前为止我的位置。注释掉的部分是我试图处理两位数的东西,但我想不出一个合乎逻辑的方法来做到这一点。我需要一些帮助来思考这个问题。

有人告诉我不要使用 eval,因为对等式“2+3*5-11/2*88+153”执行 eval 并不容易,因为运算符优先级或缺少运算符优先级其中。我的程序不应该遵守正常的运算符优先规则。相反,它应该纯粹从左到右进行评估。

 def compute(s):
    result = 0
    a = 1
    for a in range(len(s)):

    #while s[a].isdigit():
        #result = (result * 10) + int(s[a])
        #a += 1

    if s[a] == '/':

        result = result / int(s[a + 1])

    elif s[a] == '+':

        result = result + int(s[a + 1])

    elif s[a] == 'x' or s[a] == '*' or s[a] == 'X':

        result = result * int(s[a + 1])
    elif s[a] == '-':
        result = result - int(s[a + 1])
    else:
        result += int(s[a])
    a += 1
    return result

 print(compute("48+6x6/3") == 108) 

编辑这适用于单个数字。也许我们可以让它与多个数字一起工作

 def compute(s):
    result = int(s[0])
    op = 0
    a = 1
    while a < len(s):
        if s[a] == '/':
        result /= int(s[a + 1])
    elif s[a] == '+':
        result += int(s[a + 1])
    elif s[a] == '*':
        result *= int(s[a + 1])
    elif s[a] == '-':
        result -= int(s[a + 1])
    a += 1
    return int(result)

【问题讨论】:

  • 我还是不清楚。 eval 将简单地计算输入中的方程。如果输入不清楚,就像在您的示例中那样,编写算法根本没有帮助。
  • 在问题中,评估是严格从左到右的。由于我强制从左到右,因此不需要 eval 。所以像eval(str(eval(“2+3”))+”*5”) 这样的操作对于更长的方程会变得非常讨厌。
  • 使用eval 实际上是微不足道的,只要你坚持使用* 进行乘法运算。这听起来更像是您应该编写正确处理运算符优先级的代码,以便您正确地将6 + 3 * 9 评估为6 + (3 * 9),而不是简单地从左到右并将其(错误地)视为(6 + 3) * 9
  • 是的,有人告诉我将其分解为数字运算符号运算符。我只是不明白如何做到这一点的逻辑。
  • @chepner 听起来正好相反:程序应该正确处理运算符优先级。我已根据 OP 的评论将其编辑到问题中。

标签: python parsing equation slice


【解决方案1】:

使用eval 可能非常危险,如果您接受来自不受信任输入的字符串进行评估。例如假设正在评估的字符串是 "os.system('rm -rf /')" ?它会真正开始删除您计算机上的所有文件。

所以你可以用python内部的compiler解析它:

import compiler
eq="48+6*6/3"
ast= compiler.parse( eq )

>>> compiler.parse( eq )
Module(None, Stmt([Discard(Add((Const(48), Div((Mul((Const(6), Const(6))), Const(3))))))]))
>>>

您还可以使用sympy,这是一个用于符号数学的 Python 库。它旨在成为一个功能齐全的计算机代数系统(CAS),同时保持代码尽可能简单,以便易于理解和易于扩展。 SymPy 完全用 Python 编写,不需要任何外部库。

【讨论】:

  • 好的,但是您必须使用 equal 拆分方程,然后比较两个编译器的结果值。
  • 我想给出最好的方法!不容易!
  • 并不是说这很糟糕,只是根据您现在更完整的答案来帮助操作员。感谢您的 compiler.parse() 顺便说一句,我不知道!
  • 欢迎,我仍然需要更新答案
  • @Kasra:eval(ast.compile(s, '', 'eval'))is dangerous。它并不比eval(s) 更安全。
【解决方案2】:

您可以使用波兰表示法。 http://en.wikipedia.org/wiki/Polish_notation 这是一种基于堆栈的算法,用于解析和评估数据。它非常简单且被广泛使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 2017-02-19
    • 2021-03-14
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多