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

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

所以,上周我一贯在找一个小型、适用的竞赛争辩数学表达式的类库。有功夫我在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">

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372261.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

两张表的笛卡尔积用sql语句

第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小SELECT * FROM table1 CROSS JOIN table2转载于:https://www.cnblogs.com/henuyuxiang/p/6811717.html

[dpdk] 读官方文档(3)

续前节, 测试小程序 1. 想编译测试程序首先需要设置两个环境变量,为什么呢,因为测试程序的Makefile里用了。。。 rpm装了打包好的devel包,这个rpm也会自带这两个环境变量。就是说写第三方程序的时候,习惯上&#xff0c…

比较OpenDDR和WURFL

量身定制的Web内容通常受益于定制,以考虑多种因素,例如屏幕大小,标记语言支持和图像格式支持。 此类信息存储在“设备描述存储库”(DDR)中。 WURFL和OpenDDR项目都提供了访问DDR的API,以简化并促进适应其交…

逻辑表达式——黑纸白纸

一、问题描述 有A、B、C、D、E五个人,每人额头上都贴了一张黑色或白色的纸条。五人对坐,每人都可以看到其他人额头上的纸的颜色,但都不知道自己额头上的纸的颜色。五人互相观察后, A说:“我看见有三个人额头上贴的是白…

java 1.6u29 下载_jdk1.6 64位下载|JDK 6(Java SE Development Kit)下载6u43 64位官方版_java运行环境 IT猫扑网...

jdk1.6 64位适用于x64的系统安装的java运行环境,Java SE Development Kit6是java开发人员必备的产品,也叫做jdk6,欢迎下载使用。官方介绍适用于您的计算机(windows)的 Java 软件,即 Java Runtime Environment,也称为 J…

ZK 6中的MVVM初探

MVVM与MVC 在上一篇文章中,我们已经看到Ajax框架ZK如何采用CSS选择器启发的Controller来在View中连接UI组件并监听它们的事件。 在此ZK MVC模式下, View中的UI组件无需绑定到任何Controller方法或数据对象。 使用选择器模式作为将View状态和事件映射到Co…

消失循环的2023?你都做了什么? | 2023 年度总结

2023年度总结 -- 今年都做了什么事? 前言心态关键词感悟 记录申请软著独立游戏技术成长 共勉 前言 又到了一年一次年度总结的时候了。我们常常感叹时间飞逝,却又没办法让它放慢的脚步。那就将2023写下来,让它在时间的长河中留下一丝记忆。 心…

由于SSH配置文件的不匹配,导致的Permission denied (publickey)及其解决方法

读者如要转载,请标明出处和作者名,谢谢。 地址01:http://space.itpub.net/25851087 地址02:http://www.cnblogs.com/zjrodger/ 作者名:zjrodger 【问题发生环境和相关参数】(1)OS:Win7 32Bit. (2)Git&#…

java语言基本语法_Java语言基本语法

Java语言基本语法一、标识符和关键字标识符在java语言中,用来标志类名、对象名、变量名、方法名、类型名、数组名、包名的有效字符序列,称为“标识符”;标识符由字母、数字、下划线、美元符号组成,且第一个字符不能是数字&#xf…

Maven的鸟瞰图

我们每天要做的一件事是使用Maven通过发出诸如mvn install之类的构建命令来构建我们的项目。 然后,Maven查看我们项目的配置文件(亲切地称为POM),神奇地找出要执行的操作,并且,嘿,您的构建已完成…

node源码详解(五)

本作品采用知识共享署名 4.0 国际许可协议进行许可。转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource5 本博客同步在https://cnodejs.org/topic/56ed6735b705742136388fa6 本博客同步在http://www.cnblogs.com/papertree/p/5295344.html 在上一篇博客&#xff…

分层图+最短路算法 BZOJ 2763: [JLOI2011]飞行路线

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec Memory Limit: 128 MBDescription Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每…

java web 保护_java web项目请求控制及简单漏洞防范

背景:当时项目没用什么框架,过滤器,请求限制等都需要自己手写。1、请求加时间戳在后台过滤器中可以加判断,如果请求时间戳与服务器时间相差太大,可以返回异常,具体情况可以具体使用。请求中加时间戳的示例如…

Maven最佳实践

尽管Maven提供了“配置之上的约定”解决方案,但是仍然有足够多的必要配置引起严重的头痛。 在这篇文章中,我将与您分享一些最佳实践,以简化对POM文件的维护。 请勿使用已弃用的引用,例如$ {artifactId}或$ {pom.artifactId}。 使用…

51Nod - 1381 硬币游戏

51Nod - 1381 硬币游戏 有一个简单但是很有趣的游戏。在这个游戏中有一个硬币还有一张桌子,这张桌子上有很多平行线(如下图所示)。两条相邻平行线之间的距离是1,硬币的半径是R,然后我们来抛硬币到桌子上,抛…

Android中Activity和Fragment之间的通信

Android中Activity和Fragment之间的通信 Fragment启动Activity传数据到Fragment 举例:城市选择列表。一个Fragment启动Activity,Activity再把城市选择数据回传到Fragment中。Fragment中方法iv_city.setOnClickListener(new View.OnClickListener() {Ove…

NoSQLUnit 0.3.0发布

介绍 单元测试是一种验证应用程序中可测试的最小部分的方法。 单元测试必须遵循FIRST规则; 这些是快速,隔离,可重复,自我验证和及时的。 考虑到没有持久层(典型的关系数据库或新的NoSQL数据库)的JEE应用程…

proftpd java_Proftpd:编译安装

下载 proftpd# wget ftp://ftp.proftpd.org/distrib/source/proftpd-1.3.5a.tar.gz# wget https://github.com/proftpd/proftpd/archive/v1.3.5a.tar.gz# yum -y install gcc openssl-devel# ./configure --prefix/usr/local/proftpd/ \--sysconfdir/usr/local/proftpd/ \--ena…

javascript 相关小的知识点集合

本文主要是列出一些javascript 相关的,不限于javascript的,容易记错或者遗忘的小知识,小技巧。 1、javascript中的false 在 JavaScript,常见的 false 值: 0, 0, 0, -0, false, ,null,undefined,NaN 要注意空数组([])和…

AOS – 另外一个独特的页面滚动动画库(CSS3)

AOS 是一个用于在页面滚动的时候呈现元素动画的工具库,你可能会觉得它和 WOWJS 一样,的确他们效果是类似的。但是AOS是 CSS3 动画驱动的库,当你滚动页面的时候能让元素动起来,当页面滚回顶部的时候,元素能够回到前一个…