虽然,这个题目是有一点夺人眼球,但我真实这么做了(关是以否信任基准测试效果,这是其他一个话题)。

所以,上周我一贯在找一个小型、适用的竞赛争辩数学表达式的类库。有功夫我在stackoverflow上看到了一个帖子,里面举荐的库(Expr)真实是很快而且根抵具有我需求的一切特色。但不幸的是,它不支持供应限制变量局限(在虚拟机里面,一切变量都位于一个全局命名空间)。

所以,我做了一件正常人不会做的责任:从新发明轮子,本人编写一个解析器和实行器。那是一个下雨的周六,我想到了用一个小型递归向下的解析器,一个简化了的、可以竞赛争辩表达式的笼统语法树。笼统语法树行使一个小型变量治理助手,看起来也没什么除夜不了的。但它不是没有用。我做出一个初步的完成而且实行速度特殊快。在中止了一些测试后,更让我布满决心,它实行的一切运算都准确无误。我想与最初面提到的类库比照,确认这个竞赛争辩器究竟有多快。在没有对每一个内部轮回和其他的实行中止优化前,我不报太除夜的希冀,究竟有许多类库是商业软件。所以当我看到测试效果的时辰很惊异。上面的清单展现了一个小的基准测试,行使不合的类库竞赛争辩不合个表达式。

parsii

是我编写的库,测试时用的是最终版本。这个版本做了一些简化,好比事后竞赛争辩了常量表达式。然则没有行使任何“黑魔法”,好比生成字节码或其他相反的操作。

在功效评价中,一个用例是实行表达式”2 + (7 –

5) * 3.14159 * x^(12-10) +

sin(-3.141)”。个中X的取值局限为0到1000000。测试时先运转10次,对JIT中止预热。然后再运转15次竞赛争辩平均时辰:

PARSII: 28.3 ms

EXPR: 37.2 ms

MathEval: 7748.5 ms

JEP: 647.0 ms

MESP: 220.8 ms

JFEP: 274.3 ms

现在我敢一定,每一个类库都有本人的优势,所以不能直接对它们中止比拟。虽然如斯,使人受惊的是一个庞杂完成的轨范可以具有这么好的显示。

假定读者对编译器的事理不太意见的话,上面是一个关于编译器运起色制的庞杂引见:

同其他的解析器或编译器一样,parsii行使了传统的分词器。它将字符流转化成词法单元流,所以”4 +

38″,也就是字符数组’4′,

‘ ‘,

‘+’, ‘

‘, ’3′ ,

‘ ‘,

‘‘,

’8′被转化成:

4 (整数)

+ (符号)

3 (整数)

* (符号)

8 (整数)

分词器取到一个字符,接着剖断是一个什么类型的词法单元,然后再读入这个属于词法单元的一切字符。每一个词法单元都有类型、文本内容而且晓得肇端位置(行号和字符)。网上有许多深切的教程,所以在这里就不具体讲授了。你可以看一下源代码,但正如我说的,它只是一个初步的完成。

解析器用来将传入的词法单元流翻译成可以实行的AST(笼统语法树),它是一个传统的自上而下递归解析器。这是完成解析器最庞杂的体式格式,完整手写,没无益用对象生成。像这样的解析器只具有一个包括一切语法划定礼貌的方法。

一样,关于这类类型的解析器也有许多的教程,然则若何适合地处置责罚缺陷却穷困相关的示例。除意见析表达式的速度和准确性外,优秀的缺陷处置责罚机制是一个优秀解析器的最焦点成份之一。正如在源代码里看到的那样,完成起来并非太难题。因为解析器在解析表达式的进程傍边历来不会抛出异常,

一切的缺陷都被汇集起来,而且连续尽量中止解析。即便在第一个缺陷发生发火往后已不能胜利解析生成AST,主要的是要可以尽量的连续解析。因为在一次的实行中我们需求申报尽量多的缺陷。这样的方法也一样用在了分词器申报上。好比申报造孽花招的词法单元,例如带有2个小数点的浮点数,放到一样的缺陷列表中。

实行一个解析完成后的笼统语法树异常庞杂。每一个笼统语法树节点都包括一个竞赛争辩方法,从根节点最先到父节点会挪用这个它。这里的实行效果就是表达式的效果,一个庞杂的例子就是算数运算,包括了+、-、*等操作。

实行一个解析完成后的笼统语法树异常庞杂。每一个笼统语法树节点都包括一个竞赛争辩方法,它的父亲从根节点最先挪用此方法。算数运算,代表了+、-、*等操作。

为了增加实行时辰,轨范里运用了3种优化装备:首先,在完成解析AST后,在根节点上中止一个简化的方法挪用,而且会散布到每一个子节点。每一个节点剖断本人的子表达式中能否是有简化的表达方法。例如:对算数运算,我们搜检2个操作数能否是都是常量(数字)。假定是数字,我们将竞赛争辩表达式而且前往一个包括竞赛争辩效果的常量。对函数,假定一切的参数都是常量的话,也会中止此类优化。

在表达式中行使变量时会实行第二种优化。这里行使map用来在需求的时辰来对变量的值中止读写。这一定是有用的,而且会中止许多次的查找。所以我们有一个叫做Variable类,它包括了变量称号和变量值。在中止表达式解析时,变量在浸染域局限内(仅是一个map)只被查找一次,之后就可以一贯行使。因为每次查找都前往沟通的实例,所以在竞赛争辩表达式值时变量的接见就像读写字段一样廉价,因为我们刚刚获得了Variable类的值。

第三个也是最初一个优化极可以不是经常起浸染。然则因为易于完成,照样运用了这类尤华。它的功用根抵上和名字“延迟运算”一样,次要用于函数挪用。函数不会自动竞赛争辩一切参数值,而且挪用函数。而“延迟运算”会搜检一切的参数,自行决意哪些参数需求竞赛争辩。在if函数中可以看到它运用的实例。

parsii遵照MIT准许证受权。在GitHub上可以找到一切的源代码,而且包括了预编译的jar包。

style="display:inline-block;width:336px;height:280px"

data-ad-client="ca-pub-9611302475373562"

data-ad-slot="8266948139">

java实现表达式求值_如何编写一个高效的Java表达式求值程序相关推荐

  1. java 定时调度_怎么编写一个定时调度java程序

    目前有两种流行Spring定时器配置:Java的Timer类和OpenSymphony的Quartz. 1.Java Timer定时 首先继承java.util.TimerTask类实现run方法 i ...

  2. Java入门篇(一)——如何编写一个简单的Java程序

    最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中. 主要内容包括JavaSE.JavaEE的基础知识以及如何 ...

  3. java完整开发环境搭建_如何搭建一个完整的Java开发环境

    这篇文章主要教大家如何搭建一个完整的Java开发环境,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 作为一个Java程序员,配置一个java开发环境是必备的技能,今天给广大菜鸟初学者补上一课.环境 ...

  4. java 链表逆序代码_如何实现一个高效的单向链表逆序输出?(详解)

    需要考虑因素,高效应权衡多方面因素 数据量是否会很大 空间是否有限制 原始链表的结构是否可以更改 时间复杂度是否有限制 一个链表节点需要输出的元素有多个,例如链表中存的是自定义对象,有多个字段 题目. ...

  5. java动态数组的实现_动手编写—动态数组(Java实现)

    目录 数组基础回顾 自定义动态数组 动态数组的设计 抽象父类接口设计 抽象父类设计 动态数组之DynamicArray 补充数组缩容 全局的关系图 声明 数组基础回顾 1.数组是一种常见的数据结构,用 ...

  6. java 程序输出 赵_编写一个完整的JAVA的程序

    编写一个完整的JAVA的程序 关注:84  答案:1  mip版 解决时间 2021-02-05 08:43 提问者妳螚鬧俄螚笑 2021-02-05 02:59 1,接口Person Show()方 ...

  7. Java制作一个盒子程序_编写一个简单的Java程序,模拟计算器的功能。

    提问:编写一个简单的Java程序,模拟计算器的功能. 网友回答: 程序参考: import java.awt.*; import java.awt.event.ActionEvent; import ...

  8. java 多线程 并发 面试题_最常见的15个Java多线程,并发面试问题

    假设你有三个线程T1,T2,T3.你如何能保证线程T2在线程T1后运行,T3在T2后运行 这个线程面试问题大多是在第一轮或电话筛选轮次中会被问到的,这个多线程问题的目的是检查候选人对"joi ...

  9. 编写一个长度至少五 5 的字典,其中姓名为键和性别为值;请编写一个程序,删除性别为男的员工信息。

    题目 编写一个长度至少五 5 的字典,其中姓名为键和性别为值:请编写一个程序,删除性别为男的员工信息. 方法 用for循环读取字典的键,再用字典的get方法将值读取出来,判断是否是"男&qu ...

最新文章

  1. leetcode 82. 删除排序链表中的重复元素 II
  2. android外置传感器,Android中外接键盘的检测的实现
  3. ubuntu 重装 nvidia_nvidia-smi指令报错:Failed to initialize NVML: Driver解决
  4. 第三次学JAVA再学不好就吃翔(part78)--List类
  5. 【珍藏版】 200个机器学习 NLP Python 免费相关教程
  6. git tag — 标签相关操作
  7. RGB888颜色码与十六位(RGB565)颜色码的转换
  8. SQL注入漏洞--2
  9. 【Tensorrt】Tensorrt C++部署YOLO v5报错记录 Version tag does not match. Note: Current Version: xxx, Serializ
  10. adb无线连接控制android手机
  11. svg上传服务器无法显示,让WordPress支持上传SVG格式图片并显示在媒体库中的方法...
  12. git 加速代理设置,单仓库设置代理,指定仓库设置单独代理
  13. Type-C快充诱电方案
  14. 利用免费虚拟主机上传静态网站
  15. 轻松掌握Notification的各种用法
  16. 【Pandas处理CSV】Error tokenizing data. C error: Expected 1 fields in line XX, saw XX
  17. 《土力学与地基基础(二)》在线平时作业2
  18. wireshark 抓 蓝牙数据_使用Wireshark 抓取数据包
  19. 硬件知识:红外感应电路
  20. 用WinImage创建的映像启动后A盘不可写的解决办法

热门文章

  1. php队列失败是指什么,队列是什么意思
  2. 学习、掌握运营岗位必备的基本能力和思维
  3. php 微信小程序 循环 多选,微信小程序实现多选功能
  4. mysql查看执行计划_MySql中如何使用 explain 查询 SQL 的执行计划
  5. 早上起来CSDN的PC端主页积分变成了0
  6. XX(北京)科技股份公司为啥需要购置服务器?
  7. proxifier访问https错误_教你实现IE访问https网站不出错方法
  8. es6 语法 (函数扩展)
  9. scss-!optional
  10. 【HTML基础】表格和表单