字符串四则运算
2016-08-06 21:11
295 查看
解析字符串形式的表达式,求解四则运算
要求:
所有数字都是1-9的个位数
运算符包括+、-、*、/、(、和)
运算中间结果和最终结果为double类型
解题思路:
1、常规解法(利用栈):中缀转后缀,再求解;
2、分治法(利用正则匹配):
1)只有加减运算时,从左往右算即可
2)只有乘除运算时,从左往右算即可
3)既有乘除也有加减时,按照“+”和“-”拆分,把乘除运算表达式看做一个整体(当做一个操作数,通过情形 2)算出)
4)有括号时,先求解括号里面的表达式(按照情形 3)求解);
5)有括号嵌套时,从里向外循环求解(每一层都是情形 4));
测试代码:
要求:
所有数字都是1-9的个位数
运算符包括+、-、*、/、(、和)
运算中间结果和最终结果为double类型
解题思路:
1、常规解法(利用栈):中缀转后缀,再求解;
2、分治法(利用正则匹配):
1)只有加减运算时,从左往右算即可
2)只有乘除运算时,从左往右算即可
3)既有乘除也有加减时,按照“+”和“-”拆分,把乘除运算表达式看做一个整体(当做一个操作数,通过情形 2)算出)
4)有括号时,先求解括号里面的表达式(按照情形 3)求解);
5)有括号嵌套时,从里向外循环求解(每一层都是情形 4));
import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Arithmetic { /** * 分治法 **/ private final String plusMinusRegex = "[\\+\\-]"; // 9-(1+2*3)*4-(4+1) public double calcute(final String expression) throws Exception { StringBuilder expressionBuilder = new StringBuilder(expression); Pattern pattern = Pattern.compile("\\([\\d\\+\\-\\*/\\.]+\\)"); Matcher matcher = pattern.matcher(expression); while(matcher.find()) { int start = matcher.start(); int end = matcher.end(); double r = calWithoutBracket(expressionBuilder.toString().substring(start+1,end-1)); expressionBuilder.replace(start, end, String.valueOf(r)); matcher = pattern.matcher(expressionBuilder.toString()); } return calWithoutBracket(expressionBuilder.toString()); } // 4+2*3-5*2 public double calWithoutBracket(final String expression) throws Exception { double result = 0; String[] numberStrings = expression.split(plusMinusRegex); if(numberStrings[0].contains("*") || numberStrings[0].contains("/")) { result = multiplyAndDivide(numberStrings[0]); } else { result = Double.valueOf(numberStrings[0]); } int index = 1; Pattern pattern = Pattern.compile(plusMinusRegex); Matcher matcher = pattern.matcher(expression); while(matcher.find()) { String next = numberStrings[index]; double nextNumber = (next.contains("*") || next.contains("/")) ? multiplyAndDivide(next) : Double.valueOf(next); String op = matcher.group(); if(op.equals("+")) { result += nextNumber; } else if(op.equals("-")) { result -= nextNumber; } index++; } return result; } // 3.5/2.3*4.1 public double multiplyAndDivide(String expression) { double result = 1; String pString = "[\\*\\/]"; String[] numberStrings = expression.split(pString); if (numberStrings.length > 0) { result = Double.valueOf(numberStrings[0]); } int index = 1; Pattern pattern = Pattern.compile(pString); Matcher matcher = pattern.matcher(expression); while (matcher.find()) { String op = matcher.group(); if (op.equals("*")) { result *= Double.valueOf(numberStrings[index]); } else if (op.equals("/")) { result /= Double.valueOf(numberStrings[index]); } index++; } return result; } // 1.5-2.8+3 public double plusAndMinus(String expression) { double result = 0; String pString = "[\\+\\-]"; String[] numberStrings = expression.split(pString); if (numberStrings.length > 0) { result = Double.valueOf(numberStrings[0]); } int index = 1; Pattern pattern = Pattern.compile(pString); Matcher matcher = pattern.matcher(expression); while (matcher.find()) { String op = matcher.group(); if (op.equals("+")) { result += Double.valueOf(numberStrings[index]); } else if (op.equals("-")) { result -= Double.valueOf(numberStrings[index]); } index++; } return result; } public boolean isNumber(char ch) { return '0' <= ch && '9' >= ch; } public int charNumToInt(char num) { if (num < '0' || num > '9') throw new IllegalArgumentException( "argument is not a char of decimal number"); return num - '0'; } /** * 中缀转后缀法 **/ public double calcute2(final String expression) { final String suffixExpression = getSuffixExpression(expression); Stack<String> stack = new Stack<String>(); for(int i=0; i<suffixExpression.length(); i++) { char ch = suffixExpression.charAt(i); if(isNumber(ch)) { stack.push(String.valueOf(ch)); } else { double rightOperand = Double.valueOf(stack.pop()); double leftOperand = Double.valueOf(stack.pop()); if(ch == '+') { stack.push(String.valueOf(leftOperand + rightOperand)); } else if(ch == '-') { stack.push(String.valueOf(leftOperand - rightOperand)); } else if(ch == '*') { stack.push(String.valueOf(leftOperand * rightOperand)); } else if(ch == '/') { stack.push(String.valueOf(leftOperand / rightOperand)); } } } return Double.valueOf(stack.pop()); } public String getSuffixExpression(final String expression) { StringBuilder suffixExpression = new StringBuilder(); Stack<Character> operatorStack = new Stack<Character>(); for(int i = 0;i < expression.length(); i++) { char ch = expression.charAt(i); if(isNumber(ch)) { suffixExpression.append(ch); } else if(ch == '(') { operatorStack.push(ch); } else if(ch == ')') { char topOp; while((topOp = operatorStack.pop()) != '(') { suffixExpression.append(topOp); } } else { if(!operatorStack.empty()) { char topOp = operatorStack.peek(); while(getPriority(topOp) >= getPriority(ch)) { suffixExpression.append(operatorStack.pop()); if(operatorStack.empty()) { break; } topOp = operatorStack.peek(); } } operatorStack.push(ch); } } while(!operatorStack.empty()) { suffixExpression.append(operatorStack.pop()); } return suffixExpression.toString(); } public int getPriority(char operator) { switch (operator) { case '+': case '-': return 1; case '*': case '/': return 2; default: return -1; } } }
测试代码:
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; public class ArithmeticTest { private Arithmetic arithmetic; @Before public void setUp() throws Exception { arithmetic = new Arithmetic(); } @Test public void testIsNumber() throws Exception { assertTrue(arithmetic.isNumber('0')); assertTrue(arithmetic.isNumber('9')); assertTrue(arithmetic.isNumber('2')); assertFalse(arithmetic.isNumber('+')); } @Test public void testCharNumToInt() throws IllegalArgumentException{ assertTrue(arithmetic.charNumToInt('2') == 2); try { arithmetic.charNumToInt('+'); assertTrue(false); } catch (IllegalArgumentException e) { assertTrue(true); } } @Test public void testPlusAndMinus() throws Exception { assertTrue(arithmetic.plusAndMinus("8.5-3.2+2") == 7.3); } @Test public void testMultiplyAndDivide() throws Exception { assertTrue(arithmetic.multiplyAndDivide("4.0/2*4.1") == 8.2); } @Test public void testCalWithoutBracket() throws Exception { assertTrue(arithmetic.calWithoutBracket("4") == 4.0); } @Test public void testCalcute() throws Exception { assertTrue(arithmetic.calcute("(((5+2)*2)-(5+3))/2") == 3.0); } @Test public void testGetSuffixExpression() throws Exception { assertEquals(arithmetic.getSuffixExpression("9+7*4-(4+1)"),"974*+41+-"); } @Test public void testCalcute2() throws Exception { assertTrue(arithmetic.calcute2("(2*(4+1))") == 10.0); } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序