最近上网查了一下,竟然没有找到用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); } }
本文向大家介绍php实现简单四则运算器,包括了php实现简单四则运算器的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了php实现简单四则运算器的具体代码,供大家参考,具体内容如下 前端代码 : 后台: 效果图1: 效果图2: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍Python实现简单的四则运算计算器,包括了Python实现简单的四则运算计算器的使用技巧和注意事项,需要的朋友参考一下 一、算法 1、算法的主要思想就是将一个中缀表达式(Infix expression)转换成便于处理的后缀表达式(Postfix expression),然后借助于栈这个简单的数据结构,计算出表达式的结果。 2、关于如何讲普通的表达式转换成后缀表
For I am not ashamed of the gospel; it is the power of God for salvation to everyone who has faith, to the Jew first and also to the Greek. For in it the righteousness of God is revealed through faith
本文向大家介绍js实现随机的四则运算题目效果,包括了js实现随机的四则运算题目效果的使用技巧和注意事项,需要的朋友参考一下 本文主要介绍了随机的四则运算题目,这样就可以自动的生成随机的30个四则运算题目了。可以生成随机的四则运算题目给给小学生用,但是还是有问题,小学生啊!他们不知道负数,不知道小数。所以还要加入判定条件。具体代码如下: 这样负数和小数都没有了。 不过,小学生貌似会分数的运算。于是
let formulaStr = ""; formulaStr这个是带数字符号的字符串 正则表达式无法满足 加减乘除小括号嵌套使用,该表达式只能满足单层小括号 百度搜索很多无法满足
For I am not ashamed of the gospel; it is the power of God for salvation to everyone who has faith, to the Jew first and also to the Greek. For in it the righteousness of God is revealed through faith