Java字符串转换成算术表达式计算并输出结果,通过这个工具可以直接对字符串形式的算术表达式进行运算,并且使用非常简单。

这个工具中包含两个类 Calculator 和 ArithHelper

Calculator 代码如下:

import java.util.Collections;
import java.util.Stack;/***  算数表达式求值 *  直接调用Calculator的类方法conversion() *  传入算数表达式,将返回一个浮点值结果*  如果计算过程错误,将返回一个NaN*/
public class Calculator {private Stack<String> postfixStack = new Stack<String>();// 后缀式栈private Stack<Character> opStack = new Stack<Character>();// 运算符栈private int[] operatPriority = new int[] { 0, 3, 2, 1, -1, 1, 0, 2 };// 运用运算符ASCII码-40做索引的运算符优先级public static double conversion(String expression) {double result = 0;Calculator cal = new Calculator();try {expression = transform(expression);result = cal.calculate(expression);} catch (Exception e) {// e.printStackTrace();// 运算错误返回NaNreturn 0.0 / 0.0;}// return new String().valueOf(result);return result;}/*** 将表达式中负数的符号更改** @param expression*            例如-2+-1*(-3E-2)-(-1) 被转为 ~2+~1*(~3E~2)-(~1)* @return*/private static String transform(String expression) {char[] arr = expression.toCharArray();for (int i = 0; i < arr.length; i++) {if (arr[i] == '-') {if (i == 0) {arr[i] = '~';} else {char c = arr[i - 1];if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == 'E' || c == 'e') {arr[i] = '~';}}}}if(arr[0]=='~'||arr[1]=='('){arr[0]='-';return "0"+new String(arr);}else{return new String(arr);}}/*** 按照给定的表达式计算** @param expression*            要计算的表达式例如:5+12*(3+5)/7* @return*/public double calculate(String expression) {Stack<String> resultStack = new Stack<String>();prepare(expression);Collections.reverse(postfixStack);// 将后缀式栈反转String firstValue, secondValue, currentValue;// 参与计算的第一个值,第二个值和算术运算符while (!postfixStack.isEmpty()) {currentValue = postfixStack.pop();if (!isOperator(currentValue.charAt(0))) {// 如果不是运算符则存入操作数栈中currentValue = currentValue.replace("~", "-");resultStack.push(currentValue);} else {// 如果是运算符则从操作数栈中取两个值和该数值一起参与运算secondValue = resultStack.pop();firstValue = resultStack.pop();// 将负数标记符改为负号firstValue = firstValue.replace("~", "-");secondValue = secondValue.replace("~", "-");String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0));resultStack.push(tempResult);}}return Double.valueOf(resultStack.pop());}/*** 数据准备阶段将表达式转换成为后缀式栈* * @param expression*/private void prepare(String expression) {opStack.push(',');// 运算符放入栈底元素逗号,此符号优先级最低char[] arr = expression.toCharArray();int currentIndex = 0;// 当前字符的位置int count = 0;// 上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值char currentOp, peekOp;// 当前操作符和栈顶操作符for (int i = 0; i < arr.length; i++) {currentOp = arr[i];if (isOperator(currentOp)) {// 如果当前字符是运算符if (count > 0) {postfixStack.push(new String(arr, currentIndex, count));// 取两个运算符之间的数字}peekOp = opStack.peek();if (currentOp == ')') {// 遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号while (opStack.peek() != '(') {postfixStack.push(String.valueOf(opStack.pop()));}opStack.pop();} else {while (currentOp != '(' && peekOp != ',' && compare(currentOp, peekOp)) {postfixStack.push(String.valueOf(opStack.pop()));peekOp = opStack.peek();}opStack.push(currentOp);}count = 0;currentIndex = i + 1;} else {count++;}}if (count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {// 最后一个字符不是括号或者其他运算符的则加入后缀式栈中postfixStack.push(new String(arr, currentIndex, count));}while (opStack.peek() != ',') {postfixStack.push(String.valueOf(opStack.pop()));// 将操作符栈中的剩余的元素添加到后缀式栈中}}/*** 判断是否为算术符号** @param c* @return*/private boolean isOperator(char c) {return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';}/*** 利用ASCII码-40做下标去算术符号优先级** @param cur* @param peek* @return*/public boolean compare(char cur, char peek) {// 如果是peek优先级高于cur,返回true,默认都是peek优先级要低boolean result = false;if (operatPriority[(peek) - 40] >= operatPriority[(cur) - 40]) {result = true;}return result;}/*** 按照给定的算术运算符做计算** @param firstValue* @param secondValue* @param currentOp* @return*/private String calculate(String firstValue, String secondValue, char currentOp) {String result = "";switch (currentOp) {case '+':result = String.valueOf(ArithHelper.add(firstValue, secondValue));break;case '-':result = String.valueOf(ArithHelper.sub(firstValue, secondValue));break;case '*':result = String.valueOf(ArithHelper.mul(firstValue, secondValue));break;case '/':result = String.valueOf(ArithHelper.div(firstValue, secondValue));break;}return result;}
}

ArithHelper 代码如下:

public class ArithHelper {// 默认除法运算精度private static final int DEF_DIV_SCALE = 16;// 这个类不能实例化private ArithHelper() {}/*** 提供精确的加法运算。** @param v1 被加数* @param v2 加数* @return 两个参数的和*/public static double add(double v1, double v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));return b1.add(b2).doubleValue();}public static double add(String v1, String v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(v1);java.math.BigDecimal b2 = new java.math.BigDecimal(v2);return b1.add(b2).doubleValue();}/*** 提供精确的减法运算。** @param v1 被减数* @param v2 减数* @return 两个参数的差*/public static double sub(double v1, double v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));return b1.subtract(b2).doubleValue();}public static double sub(String v1, String v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(v1);java.math.BigDecimal b2 = new java.math.BigDecimal(v2);return b1.subtract(b2).doubleValue();}/*** 提供精确的乘法运算。** @param v1*            被乘数* @param v2*            乘数* @return 两个参数的积*/public static double mul(double v1, double v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));return b1.multiply(b2).doubleValue();}public static double mul(String v1, String v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(v1);java.math.BigDecimal b2 = new java.math.BigDecimal(v2);return b1.multiply(b2).doubleValue();}/*** 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。** @param v1*            被除数* @param v2*            除数* @return 两个参数的商*/public static double div(double v1, double v2) {return div(v1, v2, DEF_DIV_SCALE);}public static double div(String v1, String v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(v1);java.math.BigDecimal b2 = new java.math.BigDecimal(v2);return b1.divide(b2, DEF_DIV_SCALE, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}/*** 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。** @param v1 被除数* @param v2 除数* @param scale 表示表示需要精确到小数点以后几位。* @return 两个参数的商*/public static double div(double v1, double v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");}java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));return b1.divide(b2, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}/*** 提供精确的小数位四舍五入处理。** @param v 需要四舍五入的数字* @param scale 小数点后保留几位* @return 四舍五入后的结果*/public static double round(double v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");}java.math.BigDecimal b = new java.math.BigDecimal(Double.toString(v));java.math.BigDecimal one = new java.math.BigDecimal("1");return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}public static double round(String v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");}java.math.BigDecimal b = new java.math.BigDecimal(v);java.math.BigDecimal one = new java.math.BigDecimal("1");return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}
}

使用时调用 Calculator 类的 conversion()方法,并传入算术表达式参数,即可返回一个 Double 类型的值。

使用示例:

 1 public class MathTest {2 3      public static void main(String[] args) {4      String expression = "(0*1--3)-5/-4-(3*(-2.13))";5      double result = Calculator.conversion(expression);6      System.out.println(expression + " = " + result);7      System.out.println();8      }9
10 }

控制台输出:

1

(0*1--3)-5/-4-(3*(-2.13)) = 10.64

Java 计算数学表达式(字符串解析求值工具)相关推荐

  1. 前缀中缀后缀表达式的计算求值

    原文在这里 表达式 前缀表达式(波兰表达式) 前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前 举例说明: (3+4)×5-6 对应的前缀表达式就是 - × + 3 4 5 6 前缀表达式求值 ...

  2. 前缀表达式的计算机求值

    前缀表达式的计算机求值特点 引例:某表达式的前缀形式为"+ -*^ABCD/E/F+GH",那么它的中缀形式为? 前缀表达式的操作 前缀表达式是一种没有括号的算术表达式,就是前序表 ...

  3. R语言 表达式对象的求值 eval

    R语言 表达式对象的求值 eval 模式为 "expression"的对象在Expression objects 有具体定义.它们和引用对象的列表非常相似. > ex < ...

  4. C语言实现中缀转后缀表达式,并求值

    C语言实现中缀转后缀表达式,并求值 #include <stdio.h> #include <stdlib.h> #include <ctype.h> #inclu ...

  5. pnd1 c语言,c语言实现中缀后缀前缀表达式相互转化并求值

    <c语言实现中缀后缀前缀表达式相互转化并求值>由会员分享,可在线阅读,更多相关<c语言实现中缀后缀前缀表达式相互转化并求值(21页珍藏版)>请在人人文库网上搜索. 1.1)表达 ...

  6. java的算术表达式程序,java计算数学表达式

    import java.util.EmptyStackException; import java.util.Stack; public class CaculateFunction { privat ...

  7. 使用栈解决的一类经典问题:表达式转换及求值;中缀表达式;前缀表达式,后缀表达式,中缀转前缀;中缀转后缀;后缀表达式求值;波兰式,逆波兰式

    文章目录 背景知识 表达式转换问题(考研经典) 一:手工转换 (1)中缀转前缀和中缀转后缀 (2)前缀转中缀和后缀转中缀 二:用栈实现表达式转换 (1)中缀转后缀 (2)中缀转前缀 表达式计算问题(使 ...

  8. Java计算数学表达式(字符串形式)

    我的个人博客:zhang0peter的个人博客 题目: 表达式计算II Write a program that reads an expression in a line as input and ...

  9. JAVA阈值告警字符串解析

    数据库字段 alarm_threshold 阈值 实体类: 解析json字符串中:data中根据这三个字段进行判断 @Data public class AlarmThresholdData {pri ...

最新文章

  1. 在windows中安装python
  2. Java注解是如何工作的?
  3. How to solve C library not available dtaidistance
  4. 【windows】CMake安装小结
  5. mariadb CTE示例
  6. java.io.CharConversionException isHexDigit JS转码问题
  7. 台达b2伺服说明书_三菱Q系列定位模块及伺服参数不会设置?看这一篇就够了!...
  8. python中的累乘积_Python中的连续元素最大乘积
  9. 反向索引(Inverted Index)
  10. java题1_java面试题1
  11. 华为nova3e怎么分屏_华为手机怎么分屏?边看视频边聊微信!不是所有手机都能做到...
  12. CFS完全公平调度类
  13. 招银网络科技校园招聘面试2020.10
  14. 东北财经有计算机系吗,东北财经大学计算机科学与技术专业要学哪些课程,好学吗?...
  15. Redisson(1)分布式锁——如何解决死锁问题
  16. 码链的重大突破,提升国产二维码技术话语权
  17. 常用linux 命令 -网络相关
  18. java截取视频空间的中间段
  19. 引入html5,html5-css的引入
  20. iOS--加载、滑动翻阅大量图片解决方案详解

热门文章

  1. 发送方波_室内设备发送器
  2. Star Schema完全参考手册学习笔记六
  3. Leetcode每日一题:763.partition-labels(划分字母区间)
  4. 吴恩达机器学习练习2:optimset和fminunc函数
  5. CVPR2022车道线检测Efficient Lane Detection via Curve Modeling
  6. 关于servlet中出现GET方法不能应用于此url的解决办法
  7. python实时策略_Python策略模式
  8. c语言程序设计万年历的显示,C语言程序设计万年历
  9. if name==main是什么意思_Python中if __name__ == quot;__main__quot;:是什么意思
  10. intellij快捷键linux,IntelliJ IDEA的几个常用快捷键