java中实现四则运算代码
最近上网查了一下,竟然没有找到用Java编写的四则运算的代码,就小写了一下.如有问题请大家反馈.
1.说明
代码只是实现了简单的四则运算,支持+,-,*,/,(,)只能计算出正确的表达式的值,没有对非法表达式进行校验.
2.实现方法
第一步:将输入的字符串转换为List,主要是用来将String转换为原子:数值/运算符/括号
publicListtransStr(Stringstr) { ListstrList=newArrayList(); /*获取提出数据的符号串*/ Stringtmp=str.replaceAll("\\d*",""); /*记录当前的运算符*/ StringcurLet=null; /*记录tmp字符串中第一个运算符的位置*/ intloc=0; /*符号串长度*/ intlen=tmp.length(); for(inti=0;i<len;i++) { curLet=tmp.substring(i,i+1); loc=str.indexOf(curLet); /*如果当前处理字符为(或者)*/ if(!"".equals(str.substring(0,loc).trim())) { strList.add(str.substring(0,loc).trim()); } strList.add(str.substring(loc,loc+1)); str=str.substring(loc+1); } if(0<str.length()) { strList.add(str.trim()); } returnstrList; }
第二步:将原来的中缀表达式转换为后缀表达式,在四则运算中,后缀表达式是最方便计算的
publicString[]midToEnd(ListmidList) { Stackembl=newStack(); Stackresult=newStack(); Iteratorit=midList.iterator(); StringcurStr=null; while(it.hasNext()) { curStr=(String)it.next(); /*确认是否式字符串*/ if(sign.containsKey(curStr)) { /*如果符号栈为空或者符号为(*/ if(0==embl.size()||"(".equals(curStr)) { embl.push(curStr); } else { /*如果符号为)符号栈需要出栈,直到匹配一个(为止*/ if(")".equals(curStr)) { while(!"(".equals((String)embl.peek())) { if(0>=embl.size()) { returnnull; } result.push(embl.pop()); } embl.pop(); } else { intp1=Integer.parseInt((String)sign.get(curStr)); intp2=Integer.parseInt((String)sign.get(embl.peek())); /*如果当前字符的优先级大于栈顶符号的优先级*/ if(p1>p2) { embl.push(curStr); } else { while(p1<=p2||embl.size()>0) { result.push(embl.pop()); if(0==embl.size()) { break; } p2=Integer.parseInt((String)sign.get(embl.peek())); } embl.push(curStr); } } } } else { result.push(curStr); } } while(0<embl.size()) { result.push(embl.pop()); } intlen=result.size(); String[]ret=newString[len]; for(inti=0;i<len;i++) { ret[len-i-1]=(String)result.pop(); } returnret; }
第三步:将解析后缀表达式,返回计算的最终结果
/** *解析后缀表达式,返回对应的运算结果 *@paramString[]endStr转换后的后缀表达式 *@returnObject返回运算结果如果表达式有误直接打印"InputError" */ publicObjectcalculate(String[]endStr) { intlen=endStr.length; Stackcalc=newStack(); doublep2; doublep1; for(inti=0;i<len;i++) { if(sign.containsKey(endStr[i])) { try { p2=Double.parseDouble((String)calc.pop()); p1=Double.parseDouble((String)calc.pop()); calc.push(String.valueOf(simpleCalc(p1,p2,endStr[i]))); } catch(NumberFormatExceptionex) { ex.printStackTrace(); return"InputError"; } catch(Exceptionex) { ex.printStackTrace(); return"InputError"; } } else { calc.push(endStr[i]); } } if(1==calc.size()) { returncalc.pop(); } else { return"InputError"; } } /** *实现底层的运算函数 *@paramdoublep1数字1 *@paramdoublep1数字2 *@paramStringoper运算符+-/* */ publicdoublesimpleCalc(doublep1,doublep2,Stringoper) { switch(oper.charAt(0)) { case'+': returnp1+p2; case'-': returnp1-p2; case'*': returnp1*p2; case'/': returnp1/p2; default: returnp1; } }
第四步:运算符的优先级放在了缓存中进行提取
privatestaticHashMapsign=newHashMap(); /*将运算符的优先级放入到缓存处理*/ publicCalculateExp() { sign.put(")","3"); sign.put("*","2"); sign.put("/","2"); sign.put("+","1"); sign.put("-","1"); sign.put("(","0"); }
完整代码
importjava.util.ArrayList; importjava.util.HashMap; importjava.util.Iterator; importjava.util.List; importjava.util.Stack; /** *Java实现计算表达式 *只实现有加减乘除以及括号的运算 *例如:3+12+25*(20-20/4)+10 *@authorGuoBo2009-3-16 *@version1.0 */ publicclassCalculateExp { privatestaticHashMapsign=newHashMap(); /*将运算符的优先级放入到缓存处理*/ publicCalculateExp() { sign.put(")","3"); sign.put("*","2"); sign.put("/","2"); sign.put("+","1"); sign.put("-","1"); sign.put("(","0"); } /** *@paramString输入的表达式 *@returnList解析后的字符串元素 *对输入的字符串进行解析 *转换为需要处理的数据 *例如:3+12+25*(20-20/4)+10 *转换后的结果为: *List元素为ret={3,+,12,+,25,*,(,20,-,20,-,20,/,4,),+,10} */ publicListtransStr(Stringstr) { ListstrList=newArrayList(); /*获取提出数据的符号串*/ Stringtmp=str.replaceAll("\\d*",""); /*记录当前的运算符*/ StringcurLet=null; /*记录tmp字符串中第一个运算符的位置*/ intloc=0; /*符号串长度*/ intlen=tmp.length(); for(inti=0;i<len;i++) { curLet=tmp.substring(i,i+1); loc=str.indexOf(curLet); /*如果当前处理字符为(或者)*/ if(!"".equals(str.substring(0,loc).trim())) { strList.add(str.substring(0,loc).trim()); } strList.add(str.substring(loc,loc+1)); str=str.substring(loc+1); } if(0<str.length()) { strList.add(str.trim()); } returnstrList; } /** *将表达式从中缀表达式转换为后缀表达式(波兰式) *@ParamList解析后的表达式的列表 *@returnString[]转换后的表达式字符串数组 */ publicString[]midToEnd(ListmidList) { Stackembl=newStack(); Stackresult=newStack(); Iteratorit=midList.iterator(); StringcurStr=null; while(it.hasNext()) { curStr=(String)it.next(); /*确认是否式字符串*/ if(sign.containsKey(curStr)) { /*如果符号栈为空或者符号为(*/ if(0==embl.size()||"(".equals(curStr)) { embl.push(curStr); } else { /*如果符号为)符号栈需要出栈,直到匹配一个(为止*/ if(")".equals(curStr)) { while(!"(".equals((String)embl.peek())) { if(0>=embl.size()) { returnnull; } result.push(embl.pop()); } embl.pop(); } else { intp1=Integer.parseInt((String)sign.get(curStr)); intp2=Integer.parseInt((String)sign.get(embl.peek())); /*如果当前字符的优先级大于栈顶符号的优先级*/ if(p1>p2) { embl.push(curStr); } else { while(p1<=p2||embl.size()>0) { result.push(embl.pop()); if(0==embl.size()) { break; } p2=Integer.parseInt((String)sign.get(embl.peek())); } embl.push(curStr); } } } } else { result.push(curStr); } } while(0<embl.size()) { result.push(embl.pop()); } intlen=result.size(); String[]ret=newString[len]; for(inti=0;i<len;i++) { ret[len-i-1]=(String)result.pop(); } returnret; } /** *解析后缀表达式,返回对应的运算结果 *@paramString[]endStr转换后的后缀表达式 *@returnObject返回运算结果如果表达式有误直接打印"InputError" */ publicObjectcalculate(String[]endStr) { intlen=endStr.length; Stackcalc=newStack(); doublep2; doublep1; for(inti=0;i<len;i++) { if(sign.containsKey(endStr[i])) { try { p2=Double.parseDouble((String)calc.pop()); p1=Double.parseDouble((String)calc.pop()); calc.push(String.valueOf(simpleCalc(p1,p2,endStr[i]))); } catch(NumberFormatExceptionex) { ex.printStackTrace(); return"InputError"; } catch(Exceptionex) { ex.printStackTrace(); return"InputError"; } } else { calc.push(endStr[i]); } } if(1==calc.size()) { returncalc.pop(); } else { return"InputError"; } } /** *实现底层的运算函数 *@paramdoublep1数字1 *@paramdoublep1数字2 *@paramStringoper运算符+-/* */ publicdoublesimpleCalc(doublep1,doublep2,Stringoper) { switch(oper.charAt(0)) { case'+': returnp1+p2; case'-': returnp1-p2; case'*': returnp1*p2; case'/': returnp1/p2; default: returnp1; } } /** *主控函数 */ publicstaticvoidmain(String[]args) { CalculateExpce=newCalculateExp(); Stringtmp="3+12+25*(20-20/4+10"; Stringret=(String)ce.calculate(ce.midToEnd(ce .transStr(tmp))); doublevalue=0; try { value=Double.parseDouble(ret); } catch(NumberFormatExceptionex) { System.out.print(ret); } System.out.print(value); } }
以下是其他网友的补充
代码的思路是通过正则判断计算每个最小的计算单元。以下是代码:
importjava.math.BigDecimal; importjava.util.regex.Matcher; importjava.util.regex.Pattern; /** *计算器工具类 *@authorshuqi *@date2015-7-23 *@versionsince1.0 */ publicclassCalculatorUtil{ publicstaticBigDecimalarithmetic(Stringexp){ if(!exp.matches("\\d+")){ Stringresult=parseExp(exp).replaceAll("[\\[\\]]",""); returnnewBigDecimal(result); }else{ returnnewBigDecimal(exp); } } /** *最小计数单位 * */ privatestaticStringminExp="^((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))$"; /** *不带括号的运算 */ privatestaticStringnoParentheses="^[^\\(\\)]+$"; /** *匹配乘法或者除法 */ privatestaticStringpriorOperatorExp="(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))"; /** *匹配加法和减法 */ privatestaticStringoperatorExp="(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))"; /** *匹配只带一个括号的 */ privatestaticStringminParentheses="\\([^\\(\\)]+\\)"; /** *解析计算四则运算表达式,例:2+((3+4)*2-22)/2*3 *@paramexpression *@return */ privatestaticStringparseExp(Stringexpression){ //方法进入先替换空格,在去除运算两边的()号 expression=expression.replaceAll("\\s+","").replaceAll("^\\(([^\\(\\)]+)\\)$","$1"); //最小表达式计算 if(expression.matches(minExp)){ Stringresult=calculate(expression); returnDouble.parseDouble(result)>=0?result:"["+result+"]"; } //计算不带括号的四则运算 if(expression.matches(noParentheses)){ Patternpatt=Pattern.compile(priorOperatorExp); Matchermat=patt.matcher(expression); if(mat.find()){ StringtempMinExp=mat.group(); expression=expression.replaceFirst(priorOperatorExp,parseExp(tempMinExp)); }else{ patt=Pattern.compile(operatorExp); mat=patt.matcher(expression); if(mat.find()){ StringtempMinExp=mat.group(); expression=expression.replaceFirst(operatorExp,parseExp(tempMinExp)); } } returnparseExp(expression); } //计算带括号的四则运算 Patternpatt=Pattern.compile(minParentheses); Matchermat=patt.matcher(expression); if(mat.find()){ StringtempMinExp=mat.group(); expression=expression.replaceFirst(minParentheses,parseExp(tempMinExp)); } returnparseExp(expression); } /** *计算最小单位四则运算表达式(两个数字) *@paramexp *@return */ privatestaticStringcalculate(Stringexp){ exp=exp.replaceAll("[\\[\\]]",""); Stringnumber[]=exp.replaceFirst("(\\d)[\\+\\-\\*\\/]","$1,").split(","); BigDecimalnumber1=newBigDecimal(number[0]); BigDecimalnumber2=newBigDecimal(number[1]); BigDecimalresult=null; Stringoperator=exp.replaceFirst("^.*\\d([\\+\\-\\*\\/]).+$","$1"); if("+".equals(operator)){ result=number1.add(number2); }elseif("-".equals(operator)){ result=number1.subtract(number2); }elseif("*".equals(operator)){ result=number1.multiply(number2); }elseif("/".equals(operator)){ //第二个参数为精度,第三个为四色五入的模式 result=number1.divide(number2,5,BigDecimal.ROUND_CEILING); } returnresult!=null?result.toString():null; } }
代码原本是一个博客,原来代码没有注释而且存在BUG,我稍微修稿了一哈添加了注释。在这里做个笔记,方便以后用
另为表示对原作者的敬意,附上原始代码
/** *四则运算表达式计算 *@authorpenli * */ publicclassArithmetic{ publicstaticvoidmain(Stringargs[]){ System.out.println(arithmetic("2.2+((3+4)*2-22)/2*3.2")); } publicstaticdoublearithmetic(Stringexp){ Stringresult=parseExp(exp).replaceAll("[\\[\\]]",""); returnDouble.parseDouble(result); } /** *解析计算四则运算表达式,例:2+((3+4)*2-22)/2*3 *@paramexpression *@return */ publicstaticStringparseExp(Stringexpression){ //StringnumberReg="^((?!0)\\d+(\\.\\d+(?<!0))?)|(0\\.\\d+(?<!0))$"; expression=expression.replaceAll("\\s+","").replaceAll("^\\((.+)\\)$","$1"); StringcheckExp="\\d"; StringminExp="^((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))$"; //最小表达式计算 if(expression.matches(minExp)){ Stringresult=calculate(expression); returnDouble.parseDouble(result)>=0?result:"["+result+"]"; } //计算不带括号的四则运算 StringnoParentheses="^[^\\(\\)]+$"; StringpriorOperatorExp="(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))"; StringoperatorExp="(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))"; if(expression.matches(noParentheses)){ Patternpatt=Pattern.compile(priorOperatorExp); Matchermat=patt.matcher(expression); if(mat.find()){ StringtempMinExp=mat.group(); expression=expression.replaceFirst(priorOperatorExp,parseExp(tempMinExp)); }else{ patt=Pattern.compile(operatorExp); mat=patt.matcher(expression); if(mat.find()){ StringtempMinExp=mat.group(); expression=expression.replaceFirst(operatorExp,parseExp(tempMinExp)); } } returnparseExp(expression); } //计算带括号的四则运算 StringminParentheses="\\([^\\(\\)]+\\)"; Patternpatt=Pattern.compile(minParentheses); Matchermat=patt.matcher(expression); if(mat.find()){ StringtempMinExp=mat.group(); expression=expression.replaceFirst(minParentheses,parseExp(tempMinExp)); } returnparseExp(expression); } /** *计算最小单位四则运算表达式(两个数字) *@paramexp *@return */ publicstaticStringcalculate(Stringexp){ exp=exp.replaceAll("[\\[\\]]",""); Stringnumber[]=exp.replaceFirst("(\\d)[\\+\\-\\*\\/]","$1,").split(","); BigDecimalnumber1=newBigDecimal(number[0]); BigDecimalnumber2=newBigDecimal(number[1]); BigDecimalresult=null; Stringoperator=exp.replaceFirst("^.*\\d([\\+\\-\\*\\/]).+$","$1"); if("+".equals(operator)){ result=number1.add(number2); }elseif("-".equals(operator)){ result=number1.subtract(number2); }elseif("*".equals(operator)){ result=number1.multiply(number2); }elseif("/".equals(operator)){ result=number1.divide(number2); } returnresult!=null?result.toString():null; } }
最后给大家分享一个网友的实现方法,个人感觉也很不错
importjava.util.Stack; /** *利用栈,进行四则运算的类 *用两个栈来实现算符优先,一个栈用来保存需要计算的数据numStack,一个用来保存计算优先符priStack * *基本算法实现思路为:用当前取得的运算符与priStack栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶; *若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算; *若小于,则同理,取出栈顶元素运算,将结果入操作数栈。各个优先级'('>'*'='/'>'+'='-'>')' * */ publicclassOperate{ privateStack<Character>priStack=newStack<Character>();//操作符栈 privateStack<Integer>numStack=newStack<Integer>();;//操作数栈 /** *传入需要解析的字符串,返回计算结果(此处因为时间问题,省略合法性验证) *@paramstr需要进行技术的表达式 *@return计算结果 */ publicintcaculate(Stringstr){ //1.判断string当中有没有非法字符 Stringtemp;//用来临时存放读取的字符 //2.循环开始解析字符串,当字符串解析完,且符号栈为空时,则计算完成 StringBuffertempNum=newStringBuffer();//用来临时存放数字字符串(当为多位数时) StringBufferstring=newStringBuffer().append(str);//用来保存,提高效率 while(string.length()!=0){ temp=string.substring(0,1); string.delete(0,1); //判断temp,当temp为操作符时 if(!isNum(temp)){ //1.此时的tempNum内即为需要操作的数,取出数,压栈,并且清空tempNum if(!"".equals(tempNum.toString())){ //当表达式的第一个符号为括号 intnum=Integer.parseInt(tempNum.toString()); numStack.push(num); tempNum.delete(0,tempNum.length()); } //用当前取得的运算符与栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算; //若小于,则同理,取出栈顶元素运算,将结果入操作数栈。 //判断当前运算符与栈顶元素优先级,取出元素,进行计算(因为优先级可能小于栈顶元素,还小于第二个元素等等,需要用循环判断) while(!compare(temp.charAt(0))&&(!priStack.empty())){ inta=(int)numStack.pop();//第二个运算数 intb=(int)numStack.pop();//第一个运算数 charope=priStack.pop(); intresult=0;//运算结果 switch(ope){ //如果是加号或者减号,则 case'+': result=b+a; //将操作结果放入操作数栈 numStack.push(result); break; case'-': result=b-a; //将操作结果放入操作数栈 numStack.push(result); break; case'*': result=b*a; //将操作结果放入操作数栈 numStack.push(result); break; case'/': result=b/a;//将操作结果放入操作数栈 numStack.push(result); break; } } //判断当前运算符与栈顶元素优先级,如果高,或者低于平,计算完后,将当前操作符号,放入操作符栈 if(temp.charAt(0)!='#'){ priStack.push(newCharacter(temp.charAt(0))); if(temp.charAt(0)==')'){//当栈顶为'(',而当前元素为')'时,则是括号内以算完,去掉括号 priStack.pop(); priStack.pop(); } } }else //当为非操作符时(数字) tempNum=tempNum.append(temp);//将读到的这一位数接到以读出的数后(当不是个位数的时候) } returnnumStack.pop(); } /** *判断传入的字符是不是0-9的数字 * *@paramstr *传入的字符串 *@return */ privatebooleanisNum(Stringtemp){ returntemp.matches("[0-9]"); } /** *比较当前操作符与栈顶元素操作符优先级,如果比栈顶元素优先级高,则返回true,否则返回false * *@paramstr需要进行比较的字符 *@return比较结果true代表比栈顶元素优先级高,false代表比栈顶元素优先级低 */ privatebooleancompare(charstr){ if(priStack.empty()){ //当为空时,显然当前优先级最低,返回高 returntrue; } charlast=(char)priStack.lastElement(); //如果栈顶为'('显然,优先级最低,')'不可能为栈顶。 if(last=='('){ returntrue; } switch(str){ case'#': returnfalse;//结束符 case'(': //'('优先级最高,显然返回true returntrue; case')': //')'优先级最低, returnfalse; case'*':{ //'*/'优先级只比'+-'高 if(last=='+'||last=='-') returntrue; else returnfalse; } case'/':{ if(last=='+'||last=='-') returntrue; else returnfalse; } //'+-'为最低,一直返回false case'+': returnfalse; case'-': returnfalse; } returntrue; } publicstaticvoidmain(Stringargs[]){ Operateoperate=newOperate(); intt=operate.caculate("(3+4*(4*10-10/2)#"); System.out.println(t); } }