Python 实现简单的数学表达式解析并处理

原创 2023年 12月 27日
标签: PYTHON

先打个广告:欢迎关注我的公众号,参与 文史大挑战 趣味题目。使用方法见 这篇文章

公众号:晚花行乐

正文开始:

对于任意深度的数学表达式,希望使用 Python 解析,然后按照某种规则处理其中的元素。这里最终结果只是对单个元素的字面处理,而没有涉及表达式的表示和运算。

问题

任意数学表达式,包含数字、变量、四则运算符、函数名称、括号等符号,比如下面的例子:

A * (B + 3) / SUM(C+D)

我们希望按照任意的规则去处理其中的某些类型的符号,比如:

  • 去掉函数名称,得到 A*(B+3)/(C+D)
  • 替换变量,得到 AA*(BB+3)/SUM(CC+DD)

分词-Tokenize

首先我们需要设计一个函数把表达式的每个符号分隔开,并且根据字面量的值来判断所属的类型,跟我们人类观察的方法完全一样。比如下面的表达式

A * (B + 3) / SUM(C+D)

我们从左往右观察的时候,心里会想:

A → 字母 → 变量
空格 → 忽略 → 忽略
\* → 属于[+-*/]中的一种 → 运算符
( → 属于[()]中的一种 → 括号
B → 字母 → 变量

….以此类推

那么需要设计一个 tokenize() 函数,将原始表达式逐个按照字符的字面量划分类型。同时,将这个函数设计为生成器,使代码更简洁高效。代码如下:

def tokenize(s):
    toks = re.compile(r' +|[\d\.]+|[A-Za-z_0-9]+|[\(\)]|[\+\-\*\/]')

    for match in toks.finditer(s):
        s = match.group(0)
        if s[0] == ' ':
            continue
        elif s[0] in '()':
            yield (s, s)
        elif s[0].isdigit():
            yield ('NUMBER', s)
        elif s[0].isalpha():
            yield ('FUNC', s)
        elif s[0] == '[':
            yield ('COUNTER', s)
        elif s[0] in '+-*/':
            yield ('OPER', s)
        else:
            yield ('OTHER', s)

下面看看这个函数的运行过程:

首先创建的正则表达式,用多个 | 或符号分隔多种情况,包括:空格( +)、带小数点的数字([\d\.]+)、字母数字混合([A-Za-z_0-9]+)、小括号([\(\)])、四则运算符([\+\-\*\/]

finditer()返回一个迭代器,每次迭代返回的内容是一个 Match Object,Match Object 的 group() 函数返回分组的结果,参数为 0 时,返回完整的匹配结果。

接下来根据匹配内容的第一个字符来判断所属的类型:

如果您对本文有疑问或者寻求合作,欢迎 联系邮箱邮箱已到剪贴板

标签: PYTHON
给个免费的赞吧~

精彩评论

本站 是个人网站,采用 署名协议 CC-BY-NC 授权。
欢迎转载,请保留原文链接 https://www.lfhacks.com/tech/python-expression-parser/ ,且不得用于商业用途。