首页 > 编程 > Java > 正文

java中实现四则运算代码

2019-11-26 15:00:27
字体:
来源:转载
供稿:网友

最近上网查了一下,竟然没有找到用Java编写的四则运算的代码,就小写了一下.如有问题请大家反馈.

1.说明

代码只是实现了简单的四则运算,支持+,-,*,/,(,) 只能计算出正确的表达式的值,没有对非法表达式进行校验.

2.实现方法

第一步:将输入的字符串转换为List,主要是用来将String转换为原子:数值/运算符/括号

public List transStr(String str) { List strList = new ArrayList();  /* 获取提出数据的符号串 */ String tmp = str.replaceAll("//d*", ""); /* 记录当前的运算符 */ String curLet = null; /* 记录tmp字符串中第一个运算符的位置 */ int loc = 0; /* 符号串长度 */ int len = tmp.length(); for (int i = 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()); } return strList; }

第二步: 将原来的中缀表达式转换为后缀表达式,在四则运算中,后缀表达式是最方便计算的

public String[] midToEnd(List midList) { Stack embl = new Stack(); Stack result = new Stack();  Iterator it = midList.iterator(); String curStr = 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())    {    return null;    }    result.push(embl.pop());   }   embl.pop();   }   else   {   int p1 = Integer.parseInt((String) sign.get(curStr));   int p2 = 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()); }  int len = result.size(); String[] ret = new String[len]; for (int i = 0; i < len; i++) {  ret[len - i - 1] = (String) result.pop(); }  return ret; }

第三步:将解析后缀表达式,返回计算的最终结果

/** * 解析后缀表达式,返回对应的运算结果 * @param String[] endStr 转换后的后缀表达式 * @return Object 返回运算结果 如果表达式有误直接打印"Input Error" */ public Object calculate(String[] endStr) { int len = endStr.length; Stack calc = new Stack(); double p2; double p1; for (int i = 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(NumberFormatException ex)  {   ex.printStackTrace();   return "Input Error";  }  catch(Exception ex)  {   ex.printStackTrace();   return "Input Error";  }  }  else  {  calc.push(endStr[i]);  } }  if (1 == calc.size()) {  return calc.pop(); } else {  return "Input Error"; } }  /** * 实现底层的运算函数 * @param double p1 数字1 * @param double p1 数字2 * @param String oper 运算符 +-/* */ public double simpleCalc(double p1, double p2, String oper) {  switch(oper.charAt(0)) {   case '+':     return p1 + p2;   case '-':     return p1 - p2;   case '*':     return p1 * p2;   case '/':     return p1 / p2;   default:    return p1; } }

第四步:运算符的优先级放在了缓存中进行提取

 private static HashMap sign = new HashMap(); /* 将运算符的优先级放入到缓存处理 */ public CalculateExp() { sign.put(")", "3"); sign.put("*", "2"); sign.put("/", "2"); sign.put("+", "1"); sign.put("-", "1"); sign.put("(", "0"); }

完整代码

import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Stack;/** * Java实现计算表达式 * 只实现有加减乘除以及括号的运算 * 例如: 3+12+25*(20-20/4)+10 * @author GuoBo 2009-3-16 * @version 1.0 */public class CalculateExp{	private static HashMap sign = new HashMap();	/* 将运算符的优先级放入到缓存处理 */	public CalculateExp()	{		sign.put(")", "3");		sign.put("*", "2");		sign.put("/", "2");		sign.put("+", "1");		sign.put("-", "1");		sign.put("(", "0");	}	/**	 * @param String 输入的表达式	 * @return List 解析后的字符串元素	 * 对输入的字符串进行解析	 * 转换为需要处理的数据	 * 例如:3+12+25*(20-20/4)+10	 * 转换后的结果为:	 * List 元素为 ret = {3,+,12,+,25,*,(,20,-,20,-,20,/,4,),+,10}	 */	public List transStr(String str)	{		List strList = new ArrayList();				/* 获取提出数据的符号串 */		String tmp = str.replaceAll("//d*", "");		/* 记录当前的运算符 */		String curLet = null;		/* 记录tmp字符串中第一个运算符的位置 */		int loc = 0;		/* 符号串长度 */		int len = tmp.length();		for (int i = 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());		}		return strList;	}	/**	 * 将表达式从中缀表达式转换为后缀表达式(波兰式)	 * @Param List 解析后的表达式的列表	 * @return String[] 转换后的表达式字符串数组	 */	public String[] midToEnd(List midList)	{		Stack embl = new Stack();		Stack result = new Stack();				Iterator it = midList.iterator();		String curStr = 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())							{								return null;							}							result.push(embl.pop());						}						embl.pop();					}					else					{						int p1 = Integer.parseInt((String) sign.get(curStr));						int p2 = 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());		}				int len = result.size();		String[] ret = new String[len];		for (int i = 0; i < len; i++)		{			ret[len - i - 1] = (String) result.pop();		}				return ret;	}		/**	 * 解析后缀表达式,返回对应的运算结果	 * @param String[] endStr 转换后的后缀表达式	 * @return Object 返回运算结果 如果表达式有误直接打印"Input Error"	 */	public Object calculate(String[] endStr)	{		int len = endStr.length;		Stack calc = new Stack();		double p2;		double p1;		for (int i = 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(NumberFormatException ex)				{					ex.printStackTrace();					return "Input Error";				}				catch(Exception ex)				{					ex.printStackTrace();					return "Input Error";				}			}			else			{				calc.push(endStr[i]);			}		}				if (1 == calc.size())		{			return calc.pop();		}		else		{			return "Input Error";		}	}		/**	 * 实现底层的运算函数	 * @param double p1 数字1	 * @param double p1 数字2	 * @param String oper 运算符 +-/*	 */	public double simpleCalc(double p1, double p2, String oper)	{				switch(oper.charAt(0))		{		  case '+':		    return p1 + p2;		  case '-':		    return p1 - p2;		  case '*':		    return p1 * p2;		  case '/':		    return p1 / p2;		  default:		  	return p1;		}	}		/**	 * 主控函数	 */	public static void main(String[] args)	{		CalculateExp ce = new CalculateExp();		String tmp = "3+12+25*(20-20/4+10";		String ret = (String) ce.calculate(ce.midToEnd(ce				.transStr(tmp)));		double value = 0;    try    {    	value = Double.parseDouble(ret);    }    catch (NumberFormatException ex)    {    	System.out.print(ret);    }		System.out.print(value);	}}

以下是其他网友的补充

代码的思路是通过正则判断计算每个最小的计算单元。以下是代码:

import java.math.BigDecimal;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 计算器工具类 * @author shuqi * @date 2015-7-23 * @version since 1.0 */public class CalculatorUtil { public static BigDecimal arithmetic(String exp){  if(!exp.matches("//d+")){   String result = parseExp(exp).replaceAll("[//[//]]", "");   return new BigDecimal(result);  }else{   return new BigDecimal(exp);  } } /**  * 最小计数单位  *   */ private static String minExp="^((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//]))[//+//-//*///]((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//]))$"; /**  * 不带括号的运算  */ private static String noParentheses="^[^//(//)]+$"; /**  * 匹配乘法或者除法  */ private static String priorOperatorExp="(((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//]))[//*///]((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//])))"; /**  * 匹配加法和减法  */ private static String operatorExp="(((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//]))[//+//-]((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//])))"; /**  * 匹配只带一个括号的  */ private static String minParentheses="//([^//(//)]+//)";  /**  * 解析计算四则运算表达式,例:2+((3+4)*2-22)/2*3  * @param expression  * @return  */ private static String parseExp(String expression){  //方法进入 先替换空格,在去除运算两边的()号  expression=expression.replaceAll("//s+", "").replaceAll("^//(([^//(//)]+)//)$", "$1");    //最小表达式计算  if(expression.matches(minExp)){   String result=calculate(expression);   return Double.parseDouble(result)>=0?result:"["+result+"]";  }  //计算不带括号的四则运算  if(expression.matches(noParentheses)){   Pattern patt=Pattern.compile(priorOperatorExp);   Matcher mat=patt.matcher(expression);   if(mat.find()){    String tempMinExp=mat.group();    expression=expression.replaceFirst(priorOperatorExp, parseExp(tempMinExp));   }else{    patt=Pattern.compile(operatorExp);    mat=patt.matcher(expression);        if(mat.find()){     String tempMinExp=mat.group();     expression=expression.replaceFirst(operatorExp, parseExp(tempMinExp));    }   }   return parseExp(expression);  }    //计算带括号的四则运算  Pattern patt=Pattern.compile(minParentheses);  Matcher mat=patt.matcher(expression);  if(mat.find()){   String tempMinExp=mat.group();   expression=expression.replaceFirst(minParentheses, parseExp(tempMinExp));  }  return parseExp(expression); } /**  * 计算最小单位四则运算表达式(两个数字)  * @param exp  * @return  */ private static String calculate(String exp){  exp=exp.replaceAll("[//[//]]", "");  String number[]=exp.replaceFirst("(//d)[//+//-//*///]", "$1,").split(",");  BigDecimal number1=new BigDecimal(number[0]);  BigDecimal number2=new BigDecimal(number[1]);  BigDecimal result=null;    String operator=exp.replaceFirst("^.*//d([//+//-//*///]).+$", "$1");  if("+".equals(operator)){   result=number1.add(number2);  }else if("-".equals(operator)){   result=number1.subtract(number2);  }else if("*".equals(operator)){   result=number1.multiply(number2);  }else if("/".equals(operator)){   //第二个参数为精度,第三个为四色五入的模式   result=number1.divide(number2,5,BigDecimal.ROUND_CEILING);  }    return result!=null?result.toString():null; } }

代码原本是一个博客,原来代码没有注释而且存在BUG,我稍微修稿了一哈添加了注释。在这里做个笔记,方便以后用

另为表示对原作者的敬意,附上原始代码

/** * 四则运算表达式计算 * @author penli * */public class Arithmetic { public static void main(String args[]){ System.out.println(arithmetic("2.2+((3+4)*2-22)/2*3.2")); } public static double arithmetic(String exp){ String result = parseExp(exp).replaceAll("[//[//]]", ""); return Double.parseDouble(result); } /** * 解析计算四则运算表达式,例:2+((3+4)*2-22)/2*3 * @param expression * @return */ public static String parseExp(String expression){ //String numberReg="^((?!0)//d+(//.//d+(?<!0))?)|(0//.//d+(?<!0))$"; expression=expression.replaceAll("//s+", "").replaceAll("^//((.+)//)$", "$1"); String checkExp="//d"; String minExp="^((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//]))[//+//-//*///]((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//]))$"; //最小表达式计算 if(expression.matches(minExp)){ String result=calculate(expression);  return Double.parseDouble(result)>=0?result:"["+result+"]"; } //计算不带括号的四则运算 String noParentheses="^[^//(//)]+$"; String priorOperatorExp="(((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//]))[//*///]((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//])))"; String operatorExp="(((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//]))[//+//-]((//d+(//.//d+)?)|(//[//-//d+(//.//d+)?//])))"; if(expression.matches(noParentheses)){ Pattern patt=Pattern.compile(priorOperatorExp); Matcher mat=patt.matcher(expression); if(mat.find()){ String tempMinExp=mat.group(); expression=expression.replaceFirst(priorOperatorExp, parseExp(tempMinExp)); }else{ patt=Pattern.compile(operatorExp); mat=patt.matcher(expression);  if(mat.find()){  String tempMinExp=mat.group();  expression=expression.replaceFirst(operatorExp, parseExp(tempMinExp)); } } return parseExp(expression); } //计算带括号的四则运算 String minParentheses="//([^//(//)]+//)"; Pattern patt=Pattern.compile(minParentheses); Matcher mat=patt.matcher(expression); if(mat.find()){ String tempMinExp=mat.group(); expression=expression.replaceFirst(minParentheses, parseExp(tempMinExp)); } return parseExp(expression); } /** * 计算最小单位四则运算表达式(两个数字) * @param exp * @return */ public static String calculate(String exp){ exp=exp.replaceAll("[//[//]]", ""); String number[]=exp.replaceFirst("(//d)[//+//-//*///]", "$1,").split(","); BigDecimal number1=new BigDecimal(number[0]); BigDecimal number2=new BigDecimal(number[1]); BigDecimal result=null;  String operator=exp.replaceFirst("^.*//d([//+//-//*///]).+$", "$1"); if("+".equals(operator)){ result=number1.add(number2); }else if("-".equals(operator)){ result=number1.subtract(number2); }else if("*".equals(operator)){ result=number1.multiply(number2); }else if("/".equals(operator)){ result=number1.divide(number2); }  return result!=null?result.toString():null; }}

最后给大家分享一个网友的实现方法,个人感觉也很不错

import java.util.Stack; /**  * 利用栈,进行四则运算的类  * 用两个栈来实现算符优先,一个栈用来保存需要计算的数据numStack,一个用来保存计算优先符priStack  *  * 基本算法实现思路为:用当前取得的运算符与priStack栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;  * 若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算;  * 若小于,则同理,取出栈顶元素运算,将结果入操作数栈。各个优先级'(' > '*' = '/' > '+' = '-' > ')'  *  */  public class Operate {   private Stack<Character> priStack = new Stack<Character>();// 操作符栈   private Stack<Integer> numStack = new Stack<Integer>();;// 操作数栈     /**   * 传入需要解析的字符串,返回计算结果(此处因为时间问题,省略合法性验证)   * @param str 需要进行技术的表达式   * @return 计算结果   */   public int caculate(String str) {    // 1.判断string当中有没有非法字符    String temp;// 用来临时存放读取的字符    // 2.循环开始解析字符串,当字符串解析完,且符号栈为空时,则计算完成    StringBuffer tempNum = new StringBuffer();// 用来临时存放数字字符串(当为多位数时)    StringBuffer string = new StringBuffer().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())) {       // 当表达式的第一个符号为括号       int num = Integer.parseInt(tempNum.toString());       numStack.push(num);      tempNum.delete(0, tempNum.length());      }      // 用当前取得的运算符与栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算;      // 若小于,则同理,取出栈顶元素运算,将结果入操作数栈。        // 判断当前运算符与栈顶元素优先级,取出元素,进行计算(因为优先级可能小于栈顶元素,还小于第二个元素等等,需要用循环判断)      while (!compare(temp.charAt(0)) && (!priStack.empty())) {      int a = (int) numStack.pop();// 第二个运算数       int b = (int) numStack.pop();// 第一个运算数       char ope = priStack.pop();       int result = 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(new Character(temp.charAt(0)));       if (temp.charAt(0) == ')') {// 当栈顶为'(',而当前元素为')'时,则是括号内以算完,去掉括号        priStack.pop();        priStack.pop();       }      }     } else      // 当为非操作符时(数字)      tempNum = tempNum.append(temp);// 将读到的这一位数接到以读出的数后(当不是个位数的时候)    }    return numStack.pop();   }     /**   * 判断传入的字符是不是0-9的数字   *   * @param str   *   传入的字符串   * @return   */   private boolean isNum(String temp) {    return temp.matches("[0-9]");   }     /**   * 比较当前操作符与栈顶元素操作符优先级,如果比栈顶元素优先级高,则返回true,否则返回false   *   * @param str 需要进行比较的字符   * @return 比较结果 true代表比栈顶元素优先级高,false代表比栈顶元素优先级低   */   private boolean compare(char str) {    if (priStack.empty()) {     // 当为空时,显然 当前优先级最低,返回高     return true;    }    char last = (char) priStack.lastElement();    // 如果栈顶为'('显然,优先级最低,')'不可能为栈顶。    if (last == '(') {     return true;    }    switch (str) {    case '#':     return false;// 结束符    case '(':     // '('优先级最高,显然返回true     return true;    case ')':     // ')'优先级最低,     return false;    case '*': {     // '*/'优先级只比'+-'高     if (last == '+' || last == '-')      return true;     else      return false;    }    case '/': {     if (last == '+' || last == '-')      return true;     else      return false;    }     // '+-'为最低,一直返回false    case '+':     return false;    case '-':     return false;    }    return true;   }     public static void main(String args[]) {    Operate operate = new Operate();    int t = operate.caculate("(3+4*(4*10-10/2)#");    System.out.println(t);   }    }  

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表