(给ImportNew加星标,提高Java技能)

编译:ImportNew/唐尤华

如何用Java计算"5+3"、"10-40"、"10*3"这样的算术表达式?本文介绍了可使用的常见方法及各自优缺点。

1. JDK Javascript引擎

JDK1.6开始,提供了Javascript脚本引擎。可以把 String 形式的字符串通过 engine.eval() 方法执行计算。示例如下:

import javax.script.ScriptEngineManager;

import javax.script.ScriptEngine;

import javax.script.ScriptException;

public class Test {

public static void main(String[] args) throws ScriptException{

ScriptEngineManager mgr = new ScriptEngineManager();

ScriptEngine engine = mgr.getEngineByName("JavaScript");

String foo = "40+2";

System.out.println(engine.eval(foo));

}

}

Java中的ScriptEngine理论上支持符合ECMAScript规范的语言。要确认当前Java支持哪些语言,可以执行下列代码:

import java.util.List;

import javax.script.ScriptEngineManager;

import javax.script.ScriptEngine;

import javax.script.Bindings;

import javax.script.ScriptContext;

import javax.script.ScriptEngineFactory;

public class Test {

public static void main(String[] args){

ScriptEngineManager mgr = new ScriptEngineManager();

List factories = mgr.getEngineFactories();

for (ScriptEngineFactory factory : factories)

{

System.out.println("ScriptEngineFactory Info");

String engName = factory.getEngineName();

String engVersion = factory.getEngineVersion();

String langName = factory.getLanguageName();

String langVersion = factory.getLanguageVersion();

System.out.printf("tScript Engine: %s (%s)n", engName, engVersion);

List engNames = factory.getNames();

for (String name : engNames)

{

System.out.printf("tEngine Alias: %sn", name);

}

System.out.printf("tLanguage: %s (%s)n", langName, langVersion);

}

}

}

执行完毕会看到ScriptEngine支持的语言。在我的机器上(java version "1.8.0_191")运行会看到下面的结果:

ScriptEngineFactory Info

Script Engine: Oracle Nashorn (1.8.0_191)

Engine Alias: nashorn

Engine Alias: Nashorn

Engine Alias: js

Engine Alias: JS

Engine Alias: JavaScript

Engine Alias: javascript

Engine Alias: ECMAScript

Engine Alias: ecmascript

Language: ECMAScript (ECMA - 262 Edition 5.1)

JDK支持的JavaScript来自Mozilla Rhino ECMAScript。Rhino 是一个完全使用Java语言编写的开源JavaScript实现。Rhino通常用在Java程序中,为最终用户提供脚本化能力。它被作为J2SE 6上的默认Java脚本化引擎。

既然支持脚本,那么就不仅限于普通的算术运算符,还可以使用Javascript中的Math函数。比如像下面这样:

String foo = "Math.cos(60)+Math.sin(30)";

System.out.println(engine.eval(foo));

// 输出 -1.9404446045080181

还可以支持变量。比如上面的例子中,两个角度分别用变量表示:

engine.put("angle1", 60);

engine.put("angle2", 30);

String bar = "Math.cos(angle1)+Math.sin(angle2)";

System.out.println(engine.eval(bar));

// 输出 -1.9404446045080181

这种方法的缺点在于,脚本本身可能有潜在的安全性问题,容易收到攻击。不推荐在服务端使用。

2. 第三方开发库

在Java的世界里,永远有丰富的第三方开发库可供选择,计算算术表达式也一样。下面列举一些常用的开发库。

JEXL

http://commons.apache.org/proper/commons-jexl/

Java Expression Language (JEXL) 是一个表达式语言引擎,可以用来在应用或者框架中使用。使用示例:

// 假设有一个名为 jexl 的类, 初始化了 JexlEngine 实例:

// 创建一个表达式对象进行计算

String calculateTax = taxManager.getTaxCalc(); //e.g. "((G1 + G2 + G3) * 0.1) + G4";

Expression e = jexl.createExpression( calculateTax );

// 填写上下文

JexlContext context = new MapContext();

context.set("G1", businessObject.getTotalSales());

context.set("G2", taxManager.getTaxCredit(businessObject.getYear()));

context.set("G3", businessObject.getIntercompanyPayments());

context.set("G4", -taxManager.getAllowances());

// ...

// 得到计算结果

Number result = (Number) e.evaluate(context);

更多内容可参见官网示例。

mXparser

http://mathparser.org/

mXparser的优点是支持多平台,Java、Android、dotNET等。

使用示例:

package mxparser.helloworld;

import org.mariuszgromada.math.mxparser.*;

public class HelloWorld {

public static void main(String[] args){

Expression eh = new Expression("5^2 * 7^3 * 11^1 * 67^1 * 49201^1");

Expression ew = new Expression("71^1 * 218549^1 * 6195547^1");

String h = mXparser.numberToAsciiString( eh.calculate() );

String w = mXparser.numberToAsciiString( ew.calculate() );

mXparser.consolePrintln(h + " " + w);

}

}

EvalEx

https://github.com/uklimaschewski/EvalEx

使用示例:

new Expression("123456789 + 123456789").eval(); // 246913600

new Expression("123456789 + 123456789")

.setPrecision(12)

.eval(); // 246913578

用于Java算术表达式计算的第三方库还有许多,这里不再一一列举。

3. 自己动手

要计算算术表达式计算,还可以自己动手实现Parser。有许多有名的算法,比如Dijkstra的双堆栈算法计算表达式。参考实现如下:

/******************************************************************************

* Compilation: javac Evaluate.java

* Execution: java Evaluate

* Dependencies: Stack.java

*

* Evaluates (fully parenthesized) arithmetic expressions using

* Dijkstra's two-stack algorithm.

*

* % java Evaluate

* ( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )

* 101.0

*

* % java Evaulate

* ( ( 1 + sqrt ( 5 ) ) / 2.0 )

* 1.618033988749895

*

*

* Note: the operators, operands, and parentheses must be

* separated by whitespace. Also, each operation must

* be enclosed in parentheses. For example, you must write

* ( 1 + ( 2 + 3 ) ) instead of ( 1 + 2 + 3 ).

* See EvaluateDeluxe.java for a fancier version.

*

*

* Remarkably, Dijkstra's algorithm computes the same

* answer if we put each operator *after* its two operands

* instead of *between* them.

*

* % java Evaluate

* ( 1 ( ( 2 3 + ) ( 4 5 * ) * ) + )

* 101.0

*

* Moreover, in such expressions, all parentheses are redundant!

* Removing them yields an expression known as a postfix expression.

* 1 2 3 + 4 5 * * +

*

*

******************************************************************************/

public class Evaluate {

public static void main(String[] args){

Stack ops = new Stack();

Stack vals = new Stack();

while (!StdIn.isEmpty()) {

String s = StdIn.readString();

if (s.equals("(")) ;

else if (s.equals("+")) ops.push(s);

else if (s.equals("-")) ops.push(s);

else if (s.equals("*")) ops.push(s);

else if (s.equals("/")) ops.push(s);

else if (s.equals("sqrt")) ops.push(s);

else if (s.equals(")")) {

String op = ops.pop();

double v = vals.pop();

if (op.equals("+")) v = vals.pop() + v;

else if (op.equals("-")) v = vals.pop() - v;

else if (op.equals("*")) v = vals.pop() * v;

else if (op.equals("/")) v = vals.pop() / v;

else if (op.equals("sqrt")) v = Math.sqrt(v);

vals.push(v);

}

else vals.push(Double.parseDouble(s));

}

StdOut.println(vals.pop());

}

}

总结

用Java进行算术表达式计算可以采用JDK提供的Javascript引擎、第三方库,也可以使用自定义Parser。可以根据自己的需要和项目特点自行选择合适解决方案。

祝编程愉快!

参考文章

看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

好文章,我在看❤️

原文始发于微信公众号(ImportNew):一文了解如何用 Java 进行算术表达式计算

java算术表达式_一文了解如何用 Java 进行算术表达式计算相关推荐

  1. lambda表达式java项目常用_一文带你彻底搞懂Lambda表达式

    1. 为什么使用Lambda表达式 Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  2. java sleep方法_一文搞懂 Java 线程中断!

    在之前的一文<如何"优雅"地终止一个线程>详细说明了 stop 终止线程的坏处及如何优雅地终止线程,那么还有别的可以终止线程的方法吗?答案是肯定的,它就是我们今天要分享 ...

  3. public接口可以被任何一个类实现_一文带你深入Java核心技术:对象克隆+接口与回调,还有这种操作...

    对象克隆 当拷贝一个变量时,原始变量与拷贝变量引用同一个对象,如图6-1所示.这就是说,改变一个变量所引用的对象将会对另一个变量产生影响. Employee original = new Employ ...

  4. java泛型 简书_一文带你认识Java泛型基础

    Java泛型基础 1. 认识泛型 泛型是在JDK1.5之后增加的新功能. 泛型可以解决数据的安全性问题, 主要的原理是在类声明的时候通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型. ...

  5. java虚拟机_一文彻底读懂Java虚拟机!(JVM)

    提到Java虚拟机(JVM),可能大部分人的第一印象是"难",但当让我们真正走入"JVM世界"的时候,会发现其实问题并不像我们想象中的那么复杂.唯一真正令我们恐 ...

  6. java中的拆箱和装箱是指什么_一文带你理解Java中自动装箱和拆箱

    Java中自动装箱和拆箱 装箱(Boxing),也称为包装(Wrapper),是在对象中放置原语类型(primitive type)的过程,以便原语(primitive)可以作为引用对象使用. 这里的 ...

  7. java俄罗斯方块视频_[VIP视频]【A0233】java面对对象编程-俄罗斯方块视频教程 高清视频 百度云 百度网...

    Java视频教程名称:java面对对象编程-俄罗斯方块视频教程  俄罗斯方块视频教程 $ X0 X1 Z: W4 P3 T  e. m3 q百度网盘下载链接: . M% x- I- V5 p( J 游 ...

  8. java 多重属性_最全面的44个Java 性能调优细节

    我认为,代码优化的最重要的作用应该是:避免未知的错误.在代码上线运行的过程中,往往会出现很多我们意想不到的错误,因为线上环境和开发环境是非常不同的,错误定位到最后往往是一个非常小的原因. 然而为了解决 ...

  9. c++和java哪个难_为什么说C语言比Java难?

    C/C++,它和Java确实不太一样.C语言和C++,语言性能虽然高,但语言本身确实很难,我们更愿意称它"造轮子"的语言!也正是因为C语言和C++性能好.粒度细,所以什么都能做,只 ...

最新文章

  1. 王家豪:求实探索,青春无问西东;脚踏实地,奋斗自成芳华 | 提升之路系列...
  2. 漫话:如何给女朋友解释为什么计算机中 0.2 + 0.1 不等于 0.3 ?
  3. 神经张量网络:探索文本实体之间的关系
  4. python课程将主要介绍哪些内容-Python课程详细介绍
  5. Flink中GroupWindow和OverWindow各自的作用+window体系+文档阅读方式
  6. 深度学习(Deep Learning)综述及算法简介
  7. Nginx系列(3):Nginx配置文件nginx.conf中文详解
  8. 如何成为一个游戏制作人——第5.5章一个小游戏的框架
  9. 03_美国医疗保健行业的数据介绍
  10. java解惑-------半斤
  11. python中实现函数不限制参数的数量
  12. 050001 《拆掉思维里的墙》读后感——一些现象的解释
  13. 业务系统如何评估服务器,系统容量预估
  14. jmeter 接口测试 签名_Jmeter之API接口签名验证测试
  15. 2016年全国高中数学联赛加试T3解答
  16. 学数据挖掘就要懂数据
  17. 【构成L1笔记:飞行道具】
  18. K8S V1.23 安装--Kubeadm+contained+公网 IP 多节点部署
  19. 6个评委对5选手打分,去掉最高分和最低分,然后求出平均分就是他们的成绩。Sort函数给评分排序,在头文件algorithm中
  20. 从文艺青年到2B青年,轻博客的N种玩法

热门文章

  1. (学习笔记)【目标检测】YOLO系列简单归纳
  2. 抖音四面被拒,再战头条终获offer,在线面试指南
  3. STM32H7学习继续(STM32H7系列9) ADC
  4. hadoop组件---面向列的开源数据库(九)--python--python使用thrift连接hbase
  5. 跟着团子学SAP PS后台篇——项目编码配置 OPSJ/OPSK
  6. linux中man手册用法,Linux中man手册的使用
  7. DevOps-2:持续集成工具Jenkins构建.Net项目
  8. 机器学习项目:泰坦尼克号幸存者预测
  9. VTT字幕文件处理(vi + sed + awk)
  10. 低调的华丽:从服务器开发的角度认识 asp.net 中的回调技术