IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python学习笔记——改进调度场Shunting-yard算法,解析含有函数式的数学表达式 -> 正文阅读

[Python知识库]Python学习笔记——改进调度场Shunting-yard算法,解析含有函数式的数学表达式

改进shunting-yard调度场算法,解析含有函数式的数学表达式

在最近的量化系统开发过程中,我遇到了一个问题,需要解析用户输入的数学/逻辑表达式,并计算这个表达式的结果。解析数学表达式的经典方法是所谓的调度场算法(Shunting-yard algorithm),将数学表达式由人类易读的“中缀表达式”重写为“后缀表达式”(逆波兰表达式),从而让计算机容易计算其结果。

不过,经典的调度场算法只能处理数学/逻辑运算符表达式,如果表达式中含有函数式,它是无能为力的,充其量可以处理单变量函数例如sqrt(), sin()等等。而我的工作恰恰需要解析含有函数式的表达式,而且函数的参数个数是不确定的,例如下面的表达式:
1 + s u m ( 1 , 2 , ( 3 + 5 ) ? 4 , m a x ( 3 , ( 4 + 5 ) ? 6 ) , 7 ? 8 ) ? ( 2 + 3 ) 1+sum(1,2,(3+5)*4, max(3, (4+5)*6), 7-8) * (2+3) 1+sum(1,2,(3+5)?4,max(3,(4+5)?6),7?8)?(2+3)
这个表达式中出现了两个函数,第一个sum()有5个参数,第二个max()有2个参数。为了实现对上述表达式的解析,需要改进标准的shunting-yard调度场算法,使它能在解析表达式的同时识别并存储函数的参数个数,从而实现对函数表达式的解析。

改进的Shunting-yard算法

本文的目的并不为了介绍经典的调度场算法,如果对本算法不熟悉的同学,建议阅读这篇文章

我假设这篇文章的读者本身已经研究过调度场算法,只是为了改进它以解析函数式,这里直接给出我改进后的调度场算法,其中改进的部分用高亮显示

算法使用一个队列,记为“输出队列”
算法使用两个栈,分别记为“op栈”和“args栈”,分别用于临时存放运算符和式子中函数的参数数量

  • 当还有记号可以读取时:
  • 读取一个记号。
  • 如果这个记号表示一个数字,那么将其添加到输出队列中。
  • 如果这个记号表示一个函数,那么将其压入op栈当中,同时将数字0压入args栈中
  • 如果这个记号表示一个函数参数的分隔符,例如一个半角逗号,那么:
    • op栈当中不断地弹出操作符并且放入输出队列中去,直到栈顶部的元素为一个左括号为止。如果一直没有遇到左括号,那么要么是分隔符放错了位置,要么是括号不匹配。
    • args栈最顶端的元素+1
  • 如果这个记号表示一个操作符,记做o1,那么:
    • 只要存在另一个记为o2的操作符位于op栈的顶端,并且
    • 如果o1是左结合性的并且它的运算符优先级要小于或者等于o2的优先级,或者
    • 如果o1是右结合性的并且它的运算符优先级比o2的要低,那么:
      • 将o2从op栈的顶端弹出并且放入输出队列中(循环直至以上条件不满足为止);
    • 然后,将o1压入op栈的顶端。
  • 如果这个记号是一个左括号,那么就将其压入op栈当中。
  • 如果这个记号是一个右括号,那么:
    • 从栈当中不断地弹出操作符并且放入输出队列中,直到运算符栈顶部的元素为左括号为止。
    • 将左括号从栈的顶端弹出并丢弃。
    • 如果此时位于op栈顶端的记号表示一个函数,那么:
      • args栈最顶端的元素+1,将元素弹出,记为arg_count
      • 将op栈顶端的函数弹出并放入输出队列中去,记录该函数的参数数量为arg_count
    • 如果在找到一个左括号之前栈就已经弹出了所有元素,那么就表示在表达式中存在不匹配的括号。
  • 当再没有记号可以读取时:
    • 如果此时在栈当中还有操作符:
      • 将操作符逐个弹出并放入输出队列中。
    • 如果此时位于栈顶端的操作符是一个括号,那么就表示在表达式中存在不匹配的括号。
  • 退出算法。

后缀表达式的计算

带函数式的后缀表达式的计算方式与通常的表达式一样,唯一的区别是在计算函数值的时候,需要读取该函数的参数数量,并且从数字栈中读取相应数量的参数带入函数式计算即可。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-27 11:48:56  更:2021-08-27 11:49:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 11:38:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码