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);
}
}