java栈实现简单的计算器
2017-10-15 19:55
309 查看
/** * java栈实现简单的计算器 * 计算表达式的值 * 实现+、-、/、*、%、(、) * #表示表达式的开始与结束 */ import java.util.Stack; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Calculator { private Stack<String> operation = new Stack<String>();// 存放运算符的栈 private Stack<Double> number = new Stack<Double>();// 存放数字的栈 public static final String ERROR = "ERROR"; public String calculator(String expression) { operation.clear(); number.clear(); String[] str = getCharacters(expression); for (int i = 0; i < str.length; ++i) { if(i == 0) { // 表达式错误 if(str[i].equals(ERROR)) return ERROR; //第一个"#"入栈 operation.add(str[i]); } else { if( isNumber(str[i]) ) {// 如果是数字 //入数据栈 number.add(Double.parseDouble(str[i])); } /* * 运算符入栈规则: * 1."("直接入栈,不用判断优先级 * 2.当前扫描的运算符的优先级高于运算符栈顶的运算符优先级,将当前运算符入栈 */ if(isOperation(str[i])) { //入操作符栈 if( "(".equals(str[i]) ) {//左括号直接入栈 operation.add(str[i]); } else { if( !operation.isEmpty() ) { if(operation.isEmpty()) { number.clear(); return ERROR; } String topElement = operation.peek();// 运算符栈顶元素 int topElementLevel = getLevel(topElement); // 运算符栈顶元素优先级 int curElementLevel = getLevel(str[i]); // 当前扫描的运算符的优先级 /* * 当前扫描的运算符的优先级小于运算符栈顶的运算符优先级: * 则取出操作数栈顶前2个数和运算符栈顶符号进行运算 */ while(curElementLevel < topElementLevel) { // 运算前判断 if(operation.size() < 2 || number.size() < 2) { operation.clear(); number.clear(); return ERROR; } // 计算并将结果入栈 number.add(calc(number.pop(), number.pop(), operation.pop())); // 运算完之后重新获取运算符栈顶元素 topElement = operation.peek(); topElementLevel = getLevel(topElement); } /* * 当前扫描的运算符的优先级等于运算符栈顶的运算符优先级: * 1.若当前扫描的运算符为"+、-、*、/、%" ,则取出操作数栈顶前2个数和运算符栈顶符号进行运算 * 2.若当前扫描的运算符为")",栈顶运算符为"(",则将括号出栈 * 3.若当前扫描的运算符为"#",说明计算完毕,得到结果 */ while(curElementLevel == topElementLevel) { if( "+".equals(str[i]) || "-".equals(str[i]) || "*".equals( 4000 str[i]) || "/".equals(str[i]) || "%".equals(str[i])) { // 运算前判断 if(operation.size() < 2 || number.size() < 2) { operation.clear(); number.clear(); return ERROR; } // 计算并将结果入栈 number.add(calc(number.pop(), number.pop(), operation.pop())); // 运算完之后重新获取运算符栈顶元素 topElement = operation.peek(); topElementLevel = getLevel(topElement); } //左右括号抵消 if( ")".equals(str[i]) && "(".equals(topElement) ) { if(operation.size() < 2) { operation.clear(); number.clear(); return ERROR; } // 括号出栈 operation.pop(); //括号出栈后重新获取运算符栈顶元素 topElement = operation.peek(); topElementLevel = getLevel(topElement); break ; // 不加break可以去掉多余的左括号,否则左右括号必须一一对应 } if( "#".equals(str[i]) && "#".equals(topElement) ) { if(number.isEmpty()) { operation.clear(); return ERROR; } //得到结果 double result = number.peek(); operation.clear(); number.clear(); return result+""; } } /* * 当前扫描的运算符的优先级大于运算符栈顶的运算符优先级且不是")", * 则将当前扫描到的运算符入栈即可 */ if(curElementLevel > topElementLevel && !")".equals(str[i])) { //入栈 operation.add(str[i]); } } else { number.clear(); return ERROR; } } } } } return ERROR; } /** * 对算数表达式进行初始化处理 * @param str * @return */ private String init(String str){ /* * 算式处理,使用正则表达式 * 1.表达式开头的 +、-、*、/、%、. 前面加个0 * 2.连续符号剔除+、-、*、/、%、. * 3.匹配以连续多个左括号"("开头和以" +、-、."结束的字符串,在最后一个左括号的后面加上0 */ // step1 Pattern pattern = Pattern.compile("^[-+*/%\\.].{1,}");// 匹配第一位是 +、-、*、/、. 的字符串 Matcher matcher = pattern.matcher(str); if( matcher.matches() ) {//输出 true,验证通过 str = "0" + str; } System.out.println("第一步处理(表达式开头是 +、-、*、/、%、. 前面加个0)后的算式: [ "+str+" ]"); // step2 pattern = Pattern.compile("[-+*/%\\.]{2,}"); matcher = pattern.matcher(str); while( matcher.find() ){ String group = matcher.group(); String operation = group.substring(0,1);// 重复的运算符 if( group.replace(operation, "").length()==0 ) {// 只剔除连续相同的运算符,否则报错 str = matcher.replaceFirst(operation); matcher = pattern.matcher(str); } else return ERROR; } System.out.println("第二步处理(剔除表达式连续重复的运算符)后的算式: [ "+str+" ]"); // step3 pattern = Pattern.compile("[(][-+\\.]"); matcher = pattern.matcher(str); int startIndex = 0; int endIndex = 0; int count=0; while( matcher.find() ) {//输出 true,验证通过 startIndex = matcher.start(); endIndex = matcher.end(); // 加了多少个0就要将字符索引加多少 startIndex += count; endIndex += count; str = str.substring(0, startIndex+1) + "0" + str.substring(endIndex-1); count++;// 记录加0的个数 } System.out.println("第三步处理(左括号后面是运算符[+-.],在括号后面加0)后的算式: [ "+str+" ]"); return str; } /** * 拆分表达式 */ private String[] getCharacters(String str) { // 初始化处理表达式 str = init(str); if(ERROR.equals(str)){ return new String[]{ERROR}; } Vector<String> strs = new Vector<String>(); strs.add("#"); String charStr = ""; int startIndex = 0; String lastStr = ""; for (int i = 0; i < str.length(); ++i) { char character = str.charAt(i); if (isOperation(character)) { charStr = str.substring(startIndex, i); if(!"".equals(charStr)) { if(isNumber(charStr)) strs.add(charStr); else return new String[]{ERROR}; } strs.add(character + ""); startIndex += charStr.length() + 1; lastStr = str.substring(i+1); } } if(!"".equals(lastStr)) { strs.add(lastStr); } strs.add("#"); int size = strs.size(); String[] result = new String[size]; for (int j = 0; j < size; ++j) { result[j] = strs.get(j); } System.out.println("符号与数字分隔:" + strs); strs.clear(); strs = null; return result; } // 得到操作符的优先级别 private int getLevel(String operate) { int level = -1; switch (operate) { case "#": level = 0; break; case "(": level = 1; break; case ")": level = 1; break; case "+": level = 2; break; case "-": level = 2; break; case "/": level = 3; break; case "%": level = 3; break; case "*": level = 4; break; } return level; } /** * 判断是否为运算符号 * @param c * @return */ private boolean isOperation(char c) { if (c == '#' || c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/' || c == '%') return true; return false; } /** * 判断是否为运算符号 * @param c * @return */ private boolean isOperation(String c) { if ("#".equals(c) || "(".equals(c) || ")".equals(c) || "+".equals(c) || "-".equals(c) || "*".equals(c) || "/".equals(c) || "%".equals(c)) return true; return false; } /** * 判断字符串是否为浮点型数字 * @param str * @return */ private boolean isNumber(String str) { try { Double.parseDouble(str); return true; } catch (Exception e) { //e.printStackTrace(); return false; } } private double calc(double number1, double number2, String operate){ double result = 0; switch (operate) { case "+": result = number2 + number1; break; case "-": result = number2 - number1; break; case "*": result = number2 * number1; break; case "/": result = number2 / number1; break; case "%": result = number2 % number1; break; } return result; } public static void main(String[] args) { // test Calculator c = new Calculator(); String result = c.calculator("+1*(5+(0-(5*((-10*(2+3)))))++7)+5+((-2+10)-10+15.5%5.8)*2*(-1+2)+10.5+10-10+(-122+3)+15+(50+(+5+6.5*(-2+5)/6.5))*5+(+120-8*5)+45%100"); System.out.println( result ); } }
相关文章推荐
- 用控制台实现简单的计算器程序
- Android 简单的计算器实现
- 关于计算器的简单实现
- 安卓(java)计算器简单实现
- 利用php代码实现网页版简单的计算器功能
- PHP实现的简单四则运算计算器功能示例
- 不带有界面的简单的计算器小程序(Java语言实现)
- 简单的js实现的计算器
- js实现简单整数计算器-------Day71
- javascript-简单的计算器实现
- 编译原理:用flex和bison实现一个简单的计算器
- 面向对象-java控制台计算器简单实现[50行]
- javascript-简单的计算器实现步骤分解(附图)
- jsp实现一个简单的计算器
- python实现最简单的计算器功能源码
- 实现简单的计算器
- JS实现的简单四则运算计算器功能示例
- 数组例子2:二维数组中的行列互换和按钮控件数组实现计算器界面(暂不支持计算功能,仅界面及简单输入)
- 用python实现一个简单的计算器
- javascript:从 复选框来选中俩个数值,然后从单选框按钮来选择加减乘除运算符,实现简单的计算器.