java 解析四则混合运算表达式并计算结果
- package ch8;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Stack;
- /**
- * 四则混合运算表达式计算
- * @author Jinjichao
- *
- */
- public class Calculator {
- /**
- * 运算符枚举
- * @author Jinjichao
- *
- */
- private enum Operator {
- ADD("+", 10), SUBTRACT("-", 10), MULTIPLY("*", 20), DIVIDE("/", 20),
- PARENTHESIS_LEFT("(", 100), PARENTHESIS_RIGHT(")", 100);
- private String operator;
- private int priority;
- private Operator(String operator, int priority) {
- this.operator = operator;
- this.priority = priority;
- }
- }
- /**
- * 操作数枚举
- * @author Jinjichao
- *
- */
- private enum Operand {
- ONE("1"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"),
- SEVEN("7"), EIGHT("8"), NINE("9"), ZERO("0"), POINT(".");
- private String operand;
- private Operand(String operand) {
- this.operand = operand;
- }
- }
- /**
- * 获取字符串所对应的运算符枚举
- * @param str
- * @return
- */
- private Operator getOperator(String str) {
- for (Operator op : Operator.values()) {
- if (str.equals(op.operator)) {
- return op;
- }
- }
- return null;
- }
- /**
- * 获取字符串所对应的操作数枚举
- * @param str
- * @return
- */
- private Operand getOperand(String str) {
- for (Operand op : Operand.values()) {
- if (str.equals(op.operand)) {
- return op;
- }
- }
- return null;
- }
- /**
- * 第1步: 将运算表达式字符串分解为运算表达式List
- *
- * @param exp
- * @return
- */
- private List<String> resolveExpr(String exp) {
- List<String> list = new LinkedList<String>();
- String temp = "";
- exp = exp.replace(" ", "");
- for (int i = 0; i < exp.length(); i++) {
- String str = exp.substring(i, i + 1);
- Operator op = getOperator(str);
- Operand od = getOperand(str);
- if (op != null) {
- if (!temp.isEmpty()) {
- list.add(temp);
- temp = "";
- }
- list.add(str);
- } else if (od != null) {
- temp += str;
- } else {
- System.out.println("表达式[" + str + "]非法! ");
- return null;
- }
- }
- if (!temp.isEmpty()) {
- list.add(temp);
- }
- //System.out.println(list);
- return list;
- }
- /**
- * 第2步: 将运算表达式List转换为逆波兰表达式List
- * @param expList
- * @return
- */
- private List<String> dealExpr(List<String> expList) {
- if(expList == null) {
- return null;
- }
- List<String> list = new LinkedList<String>();
- Stack<String> stack = new Stack<String>();
- for (String str : expList) {
- Operator op = getOperator(str.substring(0, 1));
- Operand od = getOperand(str.substring(0, 1));
- if (od != null) {
- //操作数直接入队列
- list.add(str);
- } else if (op != null) {
- if (Operator.PARENTHESIS_LEFT.equals(op)) {
- //左括号入栈
- stack.push(str);
- } else if (Operator.PARENTHESIS_RIGHT.equals(op)) {
- //右括号: 循环将栈顶的运算符取出并存入队列,直到取出左括号
- while (true) {
- if (stack.empty()) {
- System.out.println("缺少左括号! ");
- return null;
- } else if (Operator.PARENTHESIS_LEFT.operator.equals(stack.peek())) {
- stack.pop();
- break;
- } else {
- list.add(stack.pop());
- }
- }
- } else {
- //非括号类运算符
- if (!stack.empty()) {
- Operator top_op = getOperator(stack.peek());
- //当前运算符优先级大于栈顶运算符优先级,或者栈顶为左括号时,当前运算符直接入栈
- if(op.priority > top_op.priority
- || Operator.PARENTHESIS_LEFT.equals(top_op)) {
- stack.push(str);
- }
- //否则,将栈顶的运算符取出并存入队列,然后将自己入栈
- else {
- list.add(stack.pop());
- stack.push(str);
- }
- } else {
- stack.push(str);
- }
- }
- }
- }
- while(!stack.empty()) {
- String str = stack.peek();
- if(Operator.PARENTHESIS_LEFT.operator.equals(str)) {
- System.out.println("缺少右括号! ");
- return null;
- } else {
- list.add(stack.pop());
- }
- }
- //System.out.println(list);
- return list;
- }
- /**
- * 操作数运算
- * @param x
- * @param y
- * @param op
- * @return
- */
- private String operation(String x, String y, Operator op) {
- double a = 0.0;
- double b = 0.0;
- try {
- a = Double.parseDouble(x);
- b = Double.parseDouble(y);
- } catch (NumberFormatException e) {
- System.out.println("操作数非法! ");
- e.printStackTrace();
- }
- switch (op) {
- case ADD:
- return String.valueOf(a + b);
- case SUBTRACT:
- return String.valueOf(a - b);
- case MULTIPLY:
- return String.valueOf(a * b);
- case DIVIDE:
- return String.valueOf(a / b);
- default:
- return null;
- }
- }
- /**
- * 第3步: 逆波兰表达式运算
- * @param exp
- * @return
- */
- public String calculate(String exp) {
- List<String> expList = dealExpr(resolveExpr(exp));
- if(expList == null) {
- return null;
- }
- Stack<String> stack = new Stack<String>();
- for(String str : expList) {
- Operator op = getOperator(str.substring(0, 1));
- Operand od = getOperand(str.substring(0, 1));
- if(od != null) {
- stack.push(str);
- } else if (op != null) {
- //目前仅针对二元运算符
- String x = "";
- String y = "";
- if(!stack.empty()) {
- y = stack.pop();
- }
- if(!stack.empty()) {
- x = stack.pop();
- }
- if(!x.isEmpty() && !x.isEmpty()) {
- String result = operation(x, y, op);
- if(result == null) {
- return null;
- }
- stack.push(result);
- } else {
- return null;
- }
- }
- }
- return stack.pop();
- }
- }
复制代码
测试一下:
- package ch8;
- /**
- * 测试
- * @author Jinjichao
- *
- */
- public class Test {
- public static void main(String[] args) {
- Calculator cal = new Calculator();
- String str = cal.calculate("( ( ( 15 / 3 ) + ( 1.5 * 2 ) + ( 20 - 12 )) - 3.2 +2.3 + 5 ) ");
- System.out.println("运算结果:" + str);
- }
- }
复制代码
运行结果:
运算结果:20.1
其他的测试案例:
<IGNORE_JS_OP>
<IGNORE_JS_OP>
<IGNORE_JS_OP>
算法原理(对照截图):
第1步、将表达式字符串分解为运算表达式List(将运算符和操作数分别分解出来)
第2步:将运算表达式List转换为逆波兰表达式List
第3步:逆波兰表达式运算
java 解析四则混合运算表达式并计算结果的更多相关文章
- 如何处理加括号的四则混合运算表达式——基于二叉树的实现(Eclipse平台 Java版)
记得上<数据结构>课程时,利用栈的特性解决过四则混合运算表达式.而如今在编写小型关系数据库的时候,编译部分要处理where后面的逻辑表达式——检查语法正确与否的同时,还要将信息传给下一个接 ...
- C语言编程学习:写的秒速计算四则混合运算项目
C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...
- 用C++实现的有理数(分数)四则混合运算计算器
实现目标 用C++实现下图所示的一个console程序: 其中: 1.加减乘除四种运算符号分别用+.-.*./表示, + 和 - 还分别用于表示正号和负号. 2.分数的分子和分母以符号 / 分隔. 3 ...
- MathExamV2.0四则混合运算计算题生成器
MathExamV2.0四则混合运算计算题生成器----211606360 丁培晖 211606343 杨宇潇 一.预估与实际 PSP2.1 Personal Software Process Sta ...
- 软件工程学习之小学四则混合运算出题软件 Version 1.00 设计思路及感想
对于小学四则混合运算出题软件的设计,通过分析设计要求,我觉得为了这个软件在今后便于功能上的扩充,可以利用上学期所学习的<编译原理>一课中的LL1语法分析及制导翻译的算法来实现.这样做的好处 ...
- 带括号的四则混合运算的算符优先算法-----java实现
1:主方法 package com.baidu; import java.text.NumberFormat;import java.util.ArrayList;import java.util.S ...
- 软件工程学习之小学四则混合运算出题软件 Version 1.1 设计思路及感想
继上次采用形式文法来生成混合运算的算式,由于算法中没有引入控制参数而导致容易产生形式累赘(多余的括号等)的算式.本次更新决定采用一种更为简单有效的生成方式,由给出的一个随机的最终答案S,通过给定的一个 ...
- java 四则混合运算 计算器
public class Counter { /**用递归算法,把括号内的公式算出然后递归 * @param args */ public static void calculator (St ...
- web四则混合运算3
一.程序要求: 可以控制下列参数: 是否有乘除法: 是否有括号(最多可以支持十个数参与计算): 数值范围: 加减有无负数: 除法有无余数! 二.设计思路 要求能够通过参数来控制有无乘除法,加减有无 ...
随机推荐
- select case when if
select case when if 的一些用法 - 马丁传奇 - 博客园 https://www.cnblogs.com/martinzhang/p/3220595.html Write a SQ ...
- LDAP方式连接AD获取用户信息
LDAP资料介绍可以参考:http://wenku.baidu.com/view/262742f9f705cc17552709f9.html ldap访问AD域的的错误一般会如下格式: Ldap lo ...
- +Java中的native关键字浅析(Java+Native+Interface)++
JNI是Java Native Interface的 缩写.从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的 ...
- YTU 2959: 代码填充--雨昕学矩阵
2959: 代码填充--雨昕学矩阵 时间限制: 1 Sec 内存限制: 128 MB 提交: 112 解决: 50 题目描述 雨昕开始学矩阵了.矩阵数乘规则:一个数k乘一个矩阵A还是一个矩阵,行数 ...
- Jquery与Dom对象相互转化
Jquery与Dom对象相互转化 jQurey对象和DOM对象的相互转换 在讨论jQurey对象和DOM对象的相互转换之前,我们先约定定义变量的风格.如果我们获取的对象是jQuery对象,那么我们 ...
- 12_传智播客iOS视频教程_注释和函数的定义和调用
OC的注释和C语言的注释一模一样.它也分单行注释和多行注释. OC程序里面当然可以定义一个函数.并且定义的方式方法和调用的方式方法和我们C语言是一模一样的.OC有什么好学的?一样还学个什么呢? 重点是 ...
- Jquery选择器大全、属性操作、css操作、文档、事件等
一.简介 定义 jQuery创始人是美国John Resig,是优秀的Javascript框架: jQuery是一个轻量级.快速简洁的javaScript库. jQuery对象 jQuery产 ...
- java数组与字符串相互转换、整型与字符串相互转换【详解】
java 数组->字符串 1.char数组(字符数组)->字符串 可以通过:使用String.copyValueOf(charArray)函数实现. 举例: char[] arr={ ...
- $Edmonds-Karp$[网络流]
\(原题戳这里\) >最大流最小割定理$(Maximum Flow, Minimum Cut Theorem): $ 网络的最大流等于最小割 具体的证明分三部分 1.任意一个流都小于等于任意一个 ...
- poj 1061 青蛙约会(扩展欧几里德)
题目链接: http://poj.org/problem?id=1061 题目大意: 中文题目,题意一目了然,就是数据范围大的出奇. 解题思路: 假设两只青蛙都跳了T次,可以列出来不定方程:p*l + ...