1. package ch8;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. import java.util.Stack;
  5. /**
  6. * 四则混合运算表达式计算
  7. * @author Jinjichao
  8. *
  9. */
  10. public class Calculator {
  11. /**
  12. * 运算符枚举
  13. * @author Jinjichao
  14. *
  15. */
  16. private enum Operator {
  17. ADD("+", 10), SUBTRACT("-", 10), MULTIPLY("*", 20), DIVIDE("/", 20),
  18. PARENTHESIS_LEFT("(", 100), PARENTHESIS_RIGHT(")", 100);
  19. private String operator;
  20. private int priority;
  21. private Operator(String operator, int priority) {
  22. this.operator = operator;
  23. this.priority = priority;
  24. }
  25. }
  26. /**
  27. * 操作数枚举
  28. * @author Jinjichao
  29. *
  30. */
  31. private enum Operand {
  32. ONE("1"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"),
  33. SEVEN("7"), EIGHT("8"), NINE("9"), ZERO("0"), POINT(".");
  34. private String operand;
  35. private Operand(String operand) {
  36. this.operand = operand;
  37. }
  38. }
  39. /**
  40. * 获取字符串所对应的运算符枚举
  41. * @param str
  42. * @return
  43. */
  44. private Operator getOperator(String str) {
  45. for (Operator op : Operator.values()) {
  46. if (str.equals(op.operator)) {
  47. return op;
  48. }
  49. }
  50. return null;
  51. }
  52. /**
  53. * 获取字符串所对应的操作数枚举
  54. * @param str
  55. * @return
  56. */
  57. private Operand getOperand(String str) {
  58. for (Operand op : Operand.values()) {
  59. if (str.equals(op.operand)) {
  60. return op;
  61. }
  62. }
  63. return null;
  64. }
  65. /**
  66. * 第1步: 将运算表达式字符串分解为运算表达式List
  67. *
  68. * @param exp
  69. * @return
  70. */
  71. private List<String> resolveExpr(String exp) {
  72. List<String> list = new LinkedList<String>();
  73. String temp = "";
  74. exp = exp.replace(" ", "");
  75. for (int i = 0; i < exp.length(); i++) {
  76. String str = exp.substring(i, i + 1);
  77. Operator op = getOperator(str);
  78. Operand od = getOperand(str);
  79. if (op != null) {
  80. if (!temp.isEmpty()) {
  81. list.add(temp);
  82. temp = "";
  83. }
  84. list.add(str);
  85. } else if (od != null) {
  86. temp += str;
  87. } else {
  88. System.out.println("表达式[" + str + "]非法! ");
  89. return null;
  90. }
  91. }
  92. if (!temp.isEmpty()) {
  93. list.add(temp);
  94. }
  95. //System.out.println(list);
  96. return list;
  97. }
  98. /**
  99. * 第2步: 将运算表达式List转换为逆波兰表达式List
  100. * @param expList
  101. * @return
  102. */
  103. private List<String> dealExpr(List<String> expList) {
  104. if(expList == null) {
  105. return null;
  106. }
  107. List<String> list = new LinkedList<String>();
  108. Stack<String> stack = new Stack<String>();
  109. for (String str : expList) {
  110. Operator op = getOperator(str.substring(0, 1));
  111. Operand od = getOperand(str.substring(0, 1));
  112. if (od != null) {
  113. //操作数直接入队列
  114. list.add(str);
  115. } else if (op != null) {
  116. if (Operator.PARENTHESIS_LEFT.equals(op)) {
  117. //左括号入栈
  118. stack.push(str);
  119. } else if (Operator.PARENTHESIS_RIGHT.equals(op)) {
  120. //右括号: 循环将栈顶的运算符取出并存入队列,直到取出左括号
  121. while (true) {
  122. if (stack.empty()) {
  123. System.out.println("缺少左括号! ");
  124. return null;
  125. } else if (Operator.PARENTHESIS_LEFT.operator.equals(stack.peek())) {
  126. stack.pop();
  127. break;
  128. } else {
  129. list.add(stack.pop());
  130. }
  131. }
  132. } else {
  133. //非括号类运算符
  134. if (!stack.empty()) {
  135. Operator top_op = getOperator(stack.peek());
  136. //当前运算符优先级大于栈顶运算符优先级,或者栈顶为左括号时,当前运算符直接入栈
  137. if(op.priority > top_op.priority
  138. || Operator.PARENTHESIS_LEFT.equals(top_op)) {
  139. stack.push(str);
  140. }
  141. //否则,将栈顶的运算符取出并存入队列,然后将自己入栈
  142. else {
  143. list.add(stack.pop());
  144. stack.push(str);
  145. }
  146. } else {
  147. stack.push(str);
  148. }
  149. }
  150. }
  151. }
  152. while(!stack.empty()) {
  153. String str = stack.peek();
  154. if(Operator.PARENTHESIS_LEFT.operator.equals(str)) {
  155. System.out.println("缺少右括号! ");
  156. return null;
  157. } else {
  158. list.add(stack.pop());
  159. }
  160. }
  161. //System.out.println(list);
  162. return list;
  163. }
  164. /**
  165. * 操作数运算
  166. * @param x
  167. * @param y
  168. * @param op
  169. * @return
  170. */
  171. private String operation(String x, String y, Operator op) {
  172. double a = 0.0;
  173. double b = 0.0;
  174. try {
  175. a = Double.parseDouble(x);
  176. b = Double.parseDouble(y);
  177. } catch (NumberFormatException e) {
  178. System.out.println("操作数非法! ");
  179. e.printStackTrace();
  180. }
  181. switch (op) {
  182. case ADD:
  183. return String.valueOf(a + b);
  184. case SUBTRACT:
  185. return String.valueOf(a - b);
  186. case MULTIPLY:
  187. return String.valueOf(a * b);
  188. case DIVIDE:
  189. return String.valueOf(a / b);
  190. default:
  191. return null;
  192. }
  193. }
  194. /**
  195. * 第3步: 逆波兰表达式运算
  196. * @param exp
  197. * @return
  198. */
  199. public String calculate(String exp) {
  200. List<String> expList = dealExpr(resolveExpr(exp));
  201. if(expList == null) {
  202. return null;
  203. }
  204. Stack<String> stack = new Stack<String>();
  205. for(String str : expList) {
  206. Operator op = getOperator(str.substring(0, 1));
  207. Operand od = getOperand(str.substring(0, 1));
  208. if(od != null) {
  209. stack.push(str);
  210. } else if (op != null) {
  211. //目前仅针对二元运算符
  212. String x = "";
  213. String y = "";
  214. if(!stack.empty()) {
  215. y = stack.pop();
  216. }
  217. if(!stack.empty()) {
  218. x = stack.pop();
  219. }
  220. if(!x.isEmpty() && !x.isEmpty()) {
  221. String result = operation(x, y, op);
  222. if(result == null) {
  223. return null;
  224. }
  225. stack.push(result);
  226. } else {
  227. return null;
  228. }
  229. }
  230. }
  231. return stack.pop();
  232. }
  233. }

复制代码

测试一下:

  1. package ch8;
  2. /**
  3. * 测试
  4. * @author Jinjichao
  5. *
  6. */
  7. public class Test {
  8. public static void main(String[] args) {
  9. Calculator cal = new Calculator();
  10. String str = cal.calculate("( ( ( 15 / 3 ) + ( 1.5 * 2 ) + ( 20 - 12 ))  - 3.2 +2.3 + 5 ) ");
  11. System.out.println("运算结果:" + str);
  12. }
  13. }

复制代码

运行结果:
运算结果:20.1
其他的测试案例:

<IGNORE_JS_OP>

1.jpg (15.44 KB)

下载附件  保存到相册

2015-8-22 16:54 上传

 

<IGNORE_JS_OP>

2.jpg (16.65 KB)

下载附件  保存到相册

2015-8-22 16:54 上传

 

<IGNORE_JS_OP>

3.jpg (19.76 KB)

下载附件  保存到相册

2015-8-22 16:54 上传

 

算法原理(对照截图):
第1步、将表达式字符串分解为运算表达式List(将运算符和操作数分别分解出来)
第2步:将运算表达式List转换为逆波兰表达式List
第3步:逆波兰表达式运算

java 解析四则混合运算表达式并计算结果的更多相关文章

  1. 如何处理加括号的四则混合运算表达式——基于二叉树的实现(Eclipse平台 Java版)

    记得上<数据结构>课程时,利用栈的特性解决过四则混合运算表达式.而如今在编写小型关系数据库的时候,编译部分要处理where后面的逻辑表达式——检查语法正确与否的同时,还要将信息传给下一个接 ...

  2. C语言编程学习:写的秒速计算四则混合运算项目

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  3. 用C++实现的有理数(分数)四则混合运算计算器

    实现目标 用C++实现下图所示的一个console程序: 其中: 1.加减乘除四种运算符号分别用+.-.*./表示, + 和 - 还分别用于表示正号和负号. 2.分数的分子和分母以符号 / 分隔. 3 ...

  4. MathExamV2.0四则混合运算计算题生成器

    MathExamV2.0四则混合运算计算题生成器----211606360 丁培晖 211606343 杨宇潇 一.预估与实际 PSP2.1 Personal Software Process Sta ...

  5. 软件工程学习之小学四则混合运算出题软件 Version 1.00 设计思路及感想

    对于小学四则混合运算出题软件的设计,通过分析设计要求,我觉得为了这个软件在今后便于功能上的扩充,可以利用上学期所学习的<编译原理>一课中的LL1语法分析及制导翻译的算法来实现.这样做的好处 ...

  6. 带括号的四则混合运算的算符优先算法-----java实现

    1:主方法 package com.baidu; import java.text.NumberFormat;import java.util.ArrayList;import java.util.S ...

  7. 软件工程学习之小学四则混合运算出题软件 Version 1.1 设计思路及感想

    继上次采用形式文法来生成混合运算的算式,由于算法中没有引入控制参数而导致容易产生形式累赘(多余的括号等)的算式.本次更新决定采用一种更为简单有效的生成方式,由给出的一个随机的最终答案S,通过给定的一个 ...

  8. java 四则混合运算 计算器

    public class Counter { /**用递归算法,把括号内的公式算出然后递归   * @param args   */ public static void calculator (St ...

  9. web四则混合运算3

    一.程序要求: 可以控制下列参数: 是否有乘除法: 是否有括号(最多可以支持十个数参与计算): 数值范围: 加减有无负数: 除法有无余数!   二.设计思路 要求能够通过参数来控制有无乘除法,加减有无 ...

随机推荐

  1. HQL语句详解

    4.3 使用HQL查询 Hibernate提供了异常强大的查询体系,使用Hibernate有多种查询方式.可以选择使用Hibernate的HQL查询,或者使用条件查询,甚至可以使用原生的SQL查询语句 ...

  2. python和python3

    1 安装python和python3的方法 如果是python,那么直接python setup.py install; 如果是python3,那么直接python3 setup.py install ...

  3. C#6.0 新功能

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. Day1 BFS算法的学习和训练

    ​ 因为自己的原因,之前没有坚持做算法的相应学习,总是觉得太难就半途而废,真的算是一个遗憾了,所以现在开始,定一个30天入门学习算法计划. ​ 我是根据<算法图解>的顺序进行安排的,自己对 ...

  5. HttpsURLConnection 安全传输(HTTPS--Secure Hypertext Transfer Protocol-安全超文本传输协议)

    HttpsURLConnection 扩展 HttpURLConnection,支持各种特定于 https 功能.此类使用 HostnameVerifier 和 SSLSocketFactory.为这 ...

  6. CodeForces-427D:Match & Catch (后缀自动机)

    Police headquarter is monitoring signal on different frequency levels. They have got two suspiciousl ...

  7. BZOJ3160【万径人踪灭】 【FFT】

    ..恩 打了四五遍 不会也背出来了.. BZOJ3160 [听说时限紧?转C++的优势么?] 上AC代码 fft /*Problem: 3160 User: cyz666 Language: C++ ...

  8. 思维导图js

    http://baike.baidu.com/view/1469162.htm?fromenter=Mind+Maps

  9. jsDoc 使用及配置!

    原文地址:http://www.cnblogs.com/hxling/archive/2012/11/27/2791067.html jsDoc 说白了就是帮助你生成JS的文档,但有个前提,就是你编写 ...

  10. 【转载】OAuth的机制原理讲解及开发流程

    1.OAuth的简述 OAuth(Open Authorization,开放授权)是为用户资源的授权定义了一个安全.开放及简单的标准,第三方无需知道用户的账号及密码,就可获取到用户的授权信息,并且这是 ...