为了账号安全,请及时绑定邮箱和手机立即绑定

如何替换“x!” 智能地使用“math.factorial(x)”

如何替换“x!” 智能地使用“math.factorial(x)”

有只小跳蛙 2021-11-30 19:22:10
我目前正在 Python 中实现一个图形计算器,您可以在其中键入自然表达式并对其进行评估。这对于大多数函数或运算符都不是问题,但由于阶乘函数由!操作数后的a 表示,因此这更加困难。我所拥有的是一个包含函数的字符串,例如:'(2x + 1)!'需要替换为:'math.factorial((2x + 1))'但是,该字符串还可能包含其他术语,例如:'2*x + (2x + 1)! - math.sin(x)' 并且阶乘术语可能不一定包含括号:'2!'我一直在努力寻找解决这个问题的方法,但无济于事,我认为该string.replace()方法不能直接做到这一点。我寻求的东西是否过于雄心勃勃,或者有什么方法可以达到我想要的结果?
查看完整描述

2 回答

?
绝地无双

TA贡献1946条经验 获得超4个赞

你的问题有两个层次的答案:(1)解决你当前的问题;(2) 解决您的一般问题。


(1) 非常简单 - 通常用于进行字符串模式匹配和替换的最常见、最通用的工具是正则表达式(RE)。您只需定义您正在寻找的模式、您想要的模式,然后将您的字符串传递给 RE 引擎。Python 有一个内置的RE 模块,称为re. 大多数语言都有类似的东西。某些语言(例如 Perl)甚至将其作为语言语法的核心部分。


模式是一系列特定字符或非特定(“通配符”)字符。因此,在您的情况下,您需要特定 '!' 之前的非特定字符。特点。您似乎建议“之前”在您的情况下表示所有非空白字符,或者如果前面的字符是 ')',则该字符与前面的 '(' 之间的所有字符。所以让我们构建该模式,从没有括号的版本开始:


[\w] - the set of characters which are letters or numbers (we need a set of

       characters that doesn't include whitespace or ')' so I'm taking some

       liberty to keep the example simple - you could always build your own

       more complex set with the '[]' pattern)

+    - at least one of them

!    - the '!' character

然后是带括号的版本:


\(  - the literal '(' character, as opposed to the special function that ( has

.   - any character

+   - at least one of them

?   - but dont be "greedy", ie. only take the smallest set of characters that

      match the pattern (will work out to be the closest pair of parentheses)

\)  - the closing ')' character

!   - the '!' character

然后我们只需要把它们放在一起。我们|用来匹配第一个模式或第二个模式。我们使用(和)来表示我们想要“捕获”的模式部分——它是 '!' 之前的那一点。以及我们稍后要使用的括号内。所以你的模式变成:


([\w]+)!|\((.+?)\)!

别担心,RE 表达式总是看起来像是有人刚刚捣碎了键盘。有一些很棒的工具,比如RegExr,可以帮助分解复杂的 RE 表达式。


最后,您只需要获取捕获并将它们粘贴到“math.factorial”中即可。\x表示第xth 场比赛。如果第一个模式匹配,\2则为空白,反之亦然,因此我们可以同时使用它们。


math.factorial(\1\2)

就是这样!这里是如何在 Python 中运行 RE 的(注意r字符串阻止 Python 尝试将其\作为转义序列进行处理):


import re

re.sub(r'([\w]+)!|\((.+?)\)!', r'math.factorial(\1\2)', '2*x + (2x + 1)! - math.sin(x) + 2!')

re.sub采用三个参数(加上一些此处未使用的可选参数):RE 模式、替换字符串和输入字符串。这产生:


'2*x + math.factorial(2x + 1) - math.sin(x) + math.factorial(2)'

这是我相信你所追求的。


现在,(2)更难了。如果您真的打算实现一个以字符串作为输入的计算器,那么您很快就会被正则表达式淹没。在可以输入的内容和 Python 可以解释的内容之间会有很多例外和变化,最终你会得到一些非常脆弱的东西,在第一次与用户接触时就会失败。如果您不打算拥有用户,那么您就非常安全 - 您可以坚持使用有效的模式。如果不是,那么您会发现模式匹配方法有点限制。


一般来说,您要解决的问题称为词法分析(或者更全面地,作为词法分析、句法分析和语义分析的三个步骤过程)。解决这个问题的标准方法是使用一种称为递归下降解析的技术。


有趣的是,Python 解释器在解释上述re语句时执行的正是这个过程——编译器和解释器都执行相同的过程,将字符串转换为可由计算机处理的标记。


你会在网上找到很多教程。它比使用 RE 稍微复杂一些,但允许更广泛的泛化。您可能想从这里的非常简短的介绍开始。


查看完整回答
反对 回复 2021-11-30
?
qq_花开花谢_0

TA贡献1835条经验 获得超7个赞

  1. 您可以删除括号并以线性形式计算所有内容,这样在解析括号时它将评估操作数,然后应用阶乘函数 - 按照写入的顺序。

  2. 或者,您可以获得!字符串中阶乘的索引,然后如果之前索引处的字符是一个 )右括号,您就知道在应用 math.factorial() 之前需要计算一个括号内的操作数。


查看完整回答
反对 回复 2021-11-30
  • 2 回答
  • 0 关注
  • 192 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信