Java实现四则运算计算器(支持括号,小数,负数)

    xiaoxiao2021-12-04  41

    Java实现四则运算计算器(支持括号,小数,负数)

    两个类,Calculator类负责主要运算逻辑,使用两个栈(符号栈和数字栈),通过出栈压栈的方式计算,MyUtils类为工具类,主要进行一些字符串校验和处理

    代码如下:

    import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Scanner; /** * @Title: Calculator.java * @desc: 加减乘除计算器,支持括号,小数,负数 * @author mengchuan.li * @date 2016年11月14日 下午1:22:39 */ public class Calculator { public static void main(String[] args) { Calculator calc = new Calculator(); Scanner s = new Scanner(System.in); System.out.println("请输入需要计算式子(输入end退出计算器):如-1.1+2*3(4*(-6+5))/(6(2+0.2)(7-3))= "); Double result; while (s.hasNextLine()) { String str = s.nextLine(); if ("end".equals(str)) { System.out.println("谢谢使用!"); break; } // 计算处理 result = calc.prepareParam(str); if (result != null) { // 处理结果并打印 System.out.println( MyUtils.formatResult(String.format("%." + MyUtils.RESULT_DECIMAL_MAX_LENGTH + "f", result))); } } } /** * * @Title: PrepareParam * @Desc: 准备计算的数据,符号 * * @param str计算式 * @return 计算结果 * */ public Double prepareParam(String str) { // 空值校验 if (null == str || "".equals(str)) { return null; } // 长度校验 if (str.length() > MyUtils.FORMAT_MAX_LENGTH) { System.out.println("表达式过长!"); return null; } // 预处理 str = str.replaceAll(" ", "");// 去空格 if ('-' == str.charAt(0)) {// 开头为负数,如-1,改为0-1 str = 0 + str; } // 校验格式 if (!MyUtils.checkFormat(str)) { System.out.println("表达式错误!"); return null; } // 处理表达式,改为标准表达式 str = MyUtils.change2StandardFormat(str); // 拆分字符和数字 String[] nums = str.split("[^.0-9]"); List<Double> numLst = new ArrayList(); for (int i = 0; i < nums.length; i++) { if (!"".equals(nums[i])) { numLst.add(Double.parseDouble(nums[i])); } } String symStr = str.replaceAll("[.0-9]", ""); return doCalculate(symStr, numLst); } /** * * @Title: doCalculate * @Desc: 计算 * * @param symStr符号串 * @param numLst数字集合 * @return 计算结果 * */ public Double doCalculate(String symStr, List<Double> numLst) { LinkedList<Character> symStack = new LinkedList<>();// 符号栈 LinkedList<Double> numStack = new LinkedList<>();// 数字栈 double result = 0; int i = 0;// numLst的标志位 int j = 0;// symStr的标志位 char sym;// 符号 double num1, num2;// 符号前后两个数 while (symStack.isEmpty() || !(symStack.getLast() == '=' && symStr.charAt(j) == '=')) {// 形如: // =8= // 则退出循环,结果为8 if (symStack.isEmpty()) { symStack.add('='); numStack.add(numLst.get(i++)); } if (MyUtils.symLvMap.get(symStr.charAt(j)) > MyUtils.symLvMap.get(symStack.getLast())) {// 比较符号优先级,若当前符号优先级大于前一个则压栈 if (symStr.charAt(j) == '(') { symStack.add(symStr.charAt(j++)); continue; } numStack.add(numLst.get(i++)); symStack.add(symStr.charAt(j++)); } else {// 当前符号优先级小于等于前一个 符号的优先级 if (symStr.charAt(j) == ')' && symStack.getLast() == '(') {// 若()之间没有符号,则“(”出栈 j++; symStack.removeLast(); continue; } if (symStack.getLast() == '(') {// “(”直接压栈 numStack.add(numLst.get(i++)); symStack.add(symStr.charAt(j++)); continue; } num2 = numStack.removeLast(); num1 = numStack.removeLast(); sym = symStack.removeLast(); switch (sym) { case '+': numStack.add(MyUtils.plus(num1, num2)); break; case '-': numStack.add(MyUtils.reduce(num1, num2)); break; case '*': numStack.add(MyUtils.multiply(num1, num2)); break; case '/': if (num2 == 0) {// 除数为0 System.out.println("存在除数为0"); return null; } numStack.add(MyUtils.divide(num1, num2)); break; } } } return numStack.removeLast(); } } import java.util.HashMap; import java.util.LinkedList; import java.util.Map; /** * @Title: MyUtils.java * @desc: 计算器工具类 * @author mengchuan.li * @date 2016年11月14日 下午3:20:44 */ public class MyUtils { public static final int FORMAT_MAX_LENGTH = 500;// 表达式最大长度限制 public static final int RESULT_DECIMAL_MAX_LENGTH = 8;// 结果小数点最大长度限制 public static final Map<Character, Integer> symLvMap = new HashMap<Character, Integer>();// 符号优先级map static { symLvMap.put('=', 0); symLvMap.put('-', 1); symLvMap.put('+', 1); symLvMap.put('*', 2); symLvMap.put('/', 2); symLvMap.put('(', 3); symLvMap.put(')', 1); // symLvMap.put('^', 3); // symLvMap.put('%', 3); } /** * * @Title: checkFormat * @Desc: 检查表达式格式是否正确 * * @param str表达式 * @return true表达式正确,false表达式错误 * */ public static boolean checkFormat(String str) { // 校验是否以“=”结尾 if ('=' != str.charAt(str.length() - 1)) { return false; } // 校验开头是否为数字或者“(” if (!(isCharNum(str.charAt(0)) || str.charAt(0) == '(')) { return false; } char c; // 校验 for (int i = 1; i < str.length() - 1; i++) { c = str.charAt(i); if (!isCorrectChar(c)) {// 字符不合法 return false; } if (!(isCharNum(c))) { if (c == '-' || c == '+' || c == '*' || c == '/') { if (c == '-' && str.charAt(i - 1) == '(') {// 1*(-2+3)的情况 continue; } if (!(isCharNum(str.charAt(i - 1)) || str.charAt(i - 1) == ')')) {// 若符号前一个不是数字或者“)”时 return false; } } if (c == '.') { if (!isCharNum(str.charAt(i - 1)) || !isCharNum(str.charAt(i + 1))) {// 校验“.”的前后是否位数字 return false; } } } } return isBracketCouple(str);// 校验括号是否配对 } /** * * @Title: change2StandardFormat * @Desc: 处理表达式格式为标准格式,如2(-1+2)(3+4)改为2*(0-1+2)*(3+4) * * @param str * @return 标准表达式 * */ public static String change2StandardFormat(String str) { StringBuilder sb = new StringBuilder(); char c; for (int i = 0; i < str.length(); i++) { c = str.charAt(i); if (i != 0 && c == '(' && (isCharNum(str.charAt(i - 1)) || str.charAt(i - 1) == ')')) { sb.append("*("); continue; } if (c == '-' && str.charAt(i - 1) == '(') { sb.append("0-"); continue; } sb.append(c); } return sb.toString(); } /** * * @Title: isBracketCouple * @Desc: 校验括号是否配对 * @param str * @return 参数 * */ public static boolean isBracketCouple(String str) { LinkedList<Character> stack = new LinkedList<>(); for (char c : str.toCharArray()) { if (c == '(') { stack.add(c); } else if (c == ')') { if (stack.isEmpty()) { return false; } stack.removeLast(); } } if (stack.isEmpty()) { return true; } else { return false; } } /** * * @Title: formatResult * @Desc: 处理计算结果的显示 * * @param str计算结果 * @return 规范的计算结果 * */ public static String formatResult(String str) { String[] ss = str.split("\\."); if (Integer.parseInt(ss[1]) == 0) { return ss[0];// 整数 } String s1 = new StringBuilder(ss[1]).reverse().toString(); int start = 0; for (int i = 0; i < s1.length(); i++) { if (s1.charAt(i) != '0') { start = i; break; } } return ss[0] + "." + new StringBuilder(s1.substring(start, s1.length())).reverse(); } /** * * @Title: isCorrectChar * @Desc: 校验字符是否合法 * * @param c * @return 参数 * */ public static boolean isCorrectChar(Character c) { if (('0' <= c && c <= '9') || c == '-' || c == '+' || c == '*' || c == '/' || c == '(' || c == ')' || c == '.') { return true; } return false; } /** * * @Title: isCharNum * @Desc: 判断是否为数字 * * @param c * @return * */ public static boolean isCharNum(Character c) { if (c >= '0' && c <= '9') { return true; } return false; } /** * * @Title: plus * @Desc: 加 * * @param num1 * @param num2 * @return 计算结果 * */ public static double plus(double num1, double num2) { return num1 + num2; } /** * * @Title: reduce * @Desc: 减 * * @param num1 * @param num2 * @return 计算结果 * */ public static double reduce(double num1, double num2) { return num1 - num2; } /** * * @Title: multiply * @Desc: 乘 * * @param num1 * @param num2 * @return 计算结果 * */ public static double multiply(double num1, double num2) { return num1 * num2; } /** * * @Title: divide * @Desc: 除 * * @param num1 * @param num2 * @return 计算结果 * */ public static double divide(double num1, double num2) { return num1 / num2; } }
    转载请注明原文地址: https://ju.6miu.com/read-680280.html

    最新回复(0)