将一个字符串方程转换为整数答案

7
如果我有一个字符串:
equation = "1+2+3+4"

我该如何将它转换为整数并使答案相等?我想的是这样的代码,但会报错。

answer = (int)equation
print(answer)

这个等式可以包含+-*/


1
你可以尝试使用逆波兰表达式算法,但你可能需要稍微修改一下输入字符串。 - Ashwini Chaudhary
4个回答

10
如果你愿意承担风险,即可能会让恶意用户在你的机器上运行任何他们想要的内容,那么你可以使用eval()

>>> equation = "1+2+3+4"
>>> eval(equation)
10

如果你的代码只接受你控制的输入,则这是最快和最简单的解决方案。如果您需要允许用户以外的一般输入,则需要寻找更严格的表达式计算器。

更新

感谢@roippi提醒我并指出上面的代码在调用代码环境中执行。因此,表达式将使用可用的局部和全局变量进行评估。像这样禁止它:

eval(equation, {'__builtins__': None})

这并不意味着使用eval()是安全的。它只是为其提供了一个干净的、空的环境来操作。恶意用户仍然可能破坏您的系统。


5

如果我们想向全世界展示一个计算器,我非常想知道黑客能否规避这个问题:

import string

def less_dangerous_eval(equation):
    if not set(equation).intersection(string.ascii_letters + '{}[]_;\n'):
        return eval(equation)
    else:
        print("illegal character")
        return None

less_dangerous_eval('1*2/3^4+(5-6)')

返回:

3

我知道这可以通过提供错误的语法(使用try/except块可修复)或操作来占用系统中的所有内存(捕获try/except可能更加棘手)来破坏它,但我目前不知道任何让别人获得控制权的方法。


1
+1,虽然我更喜欢将输入与一小组接受的字符的白名单进行比较,而不是黑名单中的其他字符,尽管我认为这里没有太大的区别。至于如何破坏它,我能想到的最接近的是 9**9**9**9**9**9 或类似的东西,可能会引发 MemoryError - rlms

1

如果你只有数字和加号,这个代码可以工作:

answer = sum(float(i) for i in equation.split('+'))

或者,如果您知道它们只会是整数。
answer = sum(int(i) for i in equation.split('+'))

如果你想要评估更多内容,我建议你做些功课:
  • 查找字符串模块(其中包含字符串.digits)

  • 数学模块,其中有你需要的操作

  • 创建逻辑以按正确顺序执行操作

祝你好运!


2
使用 math.fsum 代替 sum 来处理浮点数。 - Ashwini Chaudhary
从问题的评论来看,他实际上想处理更一般的表达式。 - David Heffernan
创建逻辑以按正确顺序执行操作,说起来很容易,做起来却不那么简单! - David Heffernan

-2

我建议您使用eval并检查输入:

def evaluate(s):
    import string
    for i in s:
        if i not in "+-*/ " + string.digits:
            return False       # input is not valid
    return eval(s)

如前所述,eval 是不安全的,并且很难保证其安全性。我记得看过一篇非常好的博客文章来解释这个问题,有人知道是什么吗?然而,ast.literal_eval 是安全的,它不允许使用 __import__ 等功能。我强烈建议在可能的情况下使用 ast.literal_eval 而不是 eval。不幸的是,在这种情况下不可能。但是,在另一种情况下,例如只需要支持加法和乘法的情况下,您可以(并且应该)使用 literal_eval

另一方面,如果这是一项旨在让您学习解析的作业,那么我建议您以不同的方式完成。我知道如果我是老师,我会对使用 eval 的答案回复“非常聪明,但这不会帮助您通过关于抽象语法树的测试。”(顺便说一下,如果您想要正确实现这个问题,抽象语法树是您应该查看的内容之一。)


-1:他指明需要支持乘法和除法。 - roippi
1
当我使用那段代码时,我会收到格式错误的字符串错误。我做错了什么? - David Heffernan
1
@DavidHeffernan:目前Python 3似乎允许在ast.literal_eval中使用+-。 我发现这一点非常令人惊讶,因为我没有立即看出它为什么应该被允许。 - DSM
即使是针对Python 3的文档,也没有明确说明表达式可以在literal_eval中进行评估。 - David Heffernan
1
@sweeneyrod 不,乘法和除法在任何Python版本下都不受支持。只有Python 3支持加法和减法。 - roippi
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接