JAVA四则运算计算器

  1. 程序的可继续开发性,由于使用了大量的集合函数等,使得程序在继续开发和维护上具有较大优势
  2. 输入后可以判定是否输入了中文的符号,并给出相应的提示
  3. 输入后可以判定是否有连续的运算符出现,如++,*+等,如果出现操作符杂糅,可以直接提示.
  4. 可以在括号前省略*,这样更符合正常书写模式习惯,如输入2(1+1)也是可以支持转换为2*(1+1)的,这点还是犹豫再一次测试输入的时候犹豫手写的输入惯性漏加上*后想到可以增添的功能
  5. 输入后可以检测到是负号-还是减号-,并且正确处理负号.
  6. 支持对于科学计数法的输入如1e2,2e-2的支持,将e看作是数字的一部分之后将整个string传给ScienceCal方法,由其方法将数字转换为正常的表达方式.
  7. 支持大数的四则运算,运算方式是采用了JAVA的库BigInteger
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;

class Cal {
    
    
    private enum Operator {
    
    
        ADD("+", 10), SUBTRACT("-", 10),
        MULTIPLY("*", 20), DIVIDE("/", 20),
        EXPONENT("^", 30), REMAINDER("%", 40),
        PARENTHESIS_LEFT("(", 100), PARENTHESIS_RIGHT(")", 100);
        private String operator;
        private int priority;

        private Operator(String operator, int priority) {
    
    
            this.operator = operator;
            this.priority = priority;
        }
    }

    private enum Operand {
    
    
        ONE("1"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"),
        SEVEN("7"), EIGHT("8"), NINE("9"), ZERO("0"), POINT("."), Science("e");
        private String operand;

        private Operand(String operand) {
    
    
            this.operand = operand;
        }
    }

    private Operator getOperator(String str) {
    
    
        for (Operator op : Operator.values()) {
    
    
            if (str.equals(op.operator)) {
    
    
                return op;
            }
        }
        return null;
    }

    private Operand getOperand(String str) {
    
    
        for (Operand op : Operand.values()) {
    
    
            if (str.equals(op.operand)) {
    
    
                return op;
            }
        }
        return null;
    }

    private String ScienceCal(String x) {
    
    
        int EPoint = x.indexOf('e');
        if (EPoint == -1) {
    
    
            return x;
        }
        else {
    
    
            String head = x.substring(0, EPoint);
            String back = x.substring(EPoint + 1);
            double a = 0.0;
            double b = 0.0;
            try {
    
    
                a = Double.parseDouble(head);
                b = Double.parseDouble(back);
            } catch (NumberFormatException e) {
    
    
                System.out.println("操作数非法! ");
                e.printStackTrace();
            }
            return String.valueOf(a * Math.pow(10, b));
        }
    }

    private List<String> resolveExpr(String exp) {
    
    //将运算表达式字符串分解为运算表达式List
        List<String> list = new LinkedList<String>();//创建一个以结点链接的list
        String temp = "";
        exp = exp.replace(" ", "");//先将所有的空格去掉

        for (int i = 0; i < exp.length(); i++) {
    
    //判定是否使用中文字符
            if (exp.charAt(i) == '(') {
    
    
                System.out.println("使用了中文字符'('");
                return null;
            }
            if (exp.charAt(i) == ')') {
    
    
                System.out.println("使用了中文字符')'");
                return null;
            }
            if (exp.charAt(i) == '。') {
    
    
                System.out.println("使用了中文字符。");
            }
        }

        //为了处理漏*问题,我们在此做一个加*操作
        StringBuilder exptmp = new StringBuilder();
        exptmp.append(exp.charAt(0));
        for (int i = 1; i < exp.length(); i++) {
    
    
            char c = exp.charAt(i);
            String str = exp.substring(i - 1, i);
            Operand od = getOperand(str);
            if (c == '(' && (od != null || exp.charAt(i - 1) == ')')) {
    
    
                exptmp.append("*(");
                continue;
            }
            exptmp.append(c);
        }
        exp = "" + exptmp;

        //为了处理负号问题,我们在此将前一个也出现了符号的情况,此时再出现-,说明输入的是一个负号
        if (exp.charAt(0) == '-') {
    
    
            exp = "0" + exp;
        }
        if (exp.charAt(0) == '+' || exp.charAt(0) == '*' || exp.charAt(0) == '/'
                || exp.charAt(0) == '^' || exp.charAt(0) == '%') {
    
    
            System.out.println("运算符杂糅! ");
            return null;
        }
        if (exp.charAt(0) == ')') {
    
    
            System.out.println("缺少左括号! ");
            return null;
        }
        for (int i = 0; i < exp.length(); i++) {
    
    
            String str = exp.substring(i, i + 1);//取出每一位
            Operator op = getOperator(str);
            Operand od = getOperand(str);
            if (op != null) {
    
    //如果存在的是操作符
                if (!temp.isEmpty() && exp.charAt(i - 1) == 'e' && exp.charAt(i) == '-' && i > 0) {
    
    //如果此时是一个操作符,且它是e,temp数组中还有东西存着
                    temp += '-';//对于负幂的处理
                }
                else if (!temp.isEmpty()) {
    
    //如果temp中不是空的话
                    list.add(ScienceCal(temp));//将之前保存的数都存到list中
                    temp = "";
                    list.add(str);//再将符号存到list中
                }
                else if (i > 0) {
    
    //如果temp中没有存数字,说明是一个连续符号输入的情况
                    if (exp.charAt(i) == '-' && (exp.charAt(i - 1) == '-' || exp.charAt(i - 1) == '+'
                            || exp.charAt(i - 1) == '*' || exp.charAt(i - 1) == '^'
                            || exp.charAt(i - 1) == '(')) {
    
    //假设这一位出现了负号,那么将负号和数字存储在一起
                        temp += str;
                    }
                    else if ((exp.charAt(i) == '+' || exp.charAt(i) == '^' || exp.charAt(i) == '*'
                            || exp.charAt(i) == '/' || exp.charAt(i) == '%') && (exp.charAt(i - 1) == '+'
                            || exp.charAt(i - 1) == '-' || exp.charAt(i - 1) == '*' || exp.charAt(i - 1) == '/'
                            || exp.charAt(i - 1) == '^' || exp.charAt(i - 1) == '%')) {
    
    
                        System.out.println("运算符杂糅! ");
                        return null;
                    }
                    else {
    
    
                        list.add(str);
                    }
                }
                else {
    
    
                    list.add(str);
                }

            }
            else if (od != null) {
    
    
                temp += str;//用来存数字
            }
            else {
    
    //出现了不该出现的符号
                System.out.println("存在非法符号" + str);
                return null;
            }
        }
        if (!temp.isEmpty()) {
    
    
            list.add(ScienceCal(temp));
        }
        return list;//将存储好的list呈递给下一步
    }

    private List<String> dealExpr(List<String> expList) {
    
    //第2步: 将运算表达式List转换为逆波兰表达式List
        if (expList == null) {
    
    
            return null;
        }
        List<String> list = new LinkedList<String>();
        Stack<String> stack = new Stack<String>();
        for (String str : expList) {
    
    //在传入的string构建的list中
            Operator op = getOperator(str.substring(0, 1));
            Operand od = getOperand(str.substring(0, 1));
            if (od != null || str.length() > 1) {
    
    //数字直接入队列
                list.add(str);
            }
            else if (op != null) {
    
    
                if (Operator.PARENTHESIS_LEFT.equals(op)) {
    
    //左括号入栈
                    stack.push(str);
                }
                else if (Operator.PARENTHESIS_RIGHT.equals(op)) {
    
    
                    //右括号: 循环将栈顶的运算符取出并存入队列,直到取出左括号
                    while (true) {
    
    
                        if (stack.empty()) {
    
    
                            System.out.println("缺少左括号! ");
                            return null;
                        }
                        else if (Operator.PARENTHESIS_LEFT.operator.equals(stack.peek())) {
    
    
                            stack.pop();
                            break;
                        }
                        else {
    
    
                            list.add(stack.pop());
                        }
                    }
                }
                else {
    
    //非括号类运算符
                    if (!stack.empty()) {
    
    
                        Operator top_op = getOperator(stack.peek());
                        //当前运算符优先级大于栈顶运算符优先级,或者栈顶为左括号时,当前运算符直接入栈
                        if (op.priority > top_op.priority
                                || Operator.PARENTHESIS_LEFT.equals(top_op)) {
    
    
                            stack.push(str);
                        }
                        //否则,将栈顶的运算符取出并存入队列,然后将自己入栈
                        else {
    
    
                            list.add(stack.pop());
                            stack.push(str);
                        }
                    }
                    else {
    
    
                        stack.push(str);
                    }
                }
            }
        }
        while (!stack.empty()) {
    
    
            String str = stack.peek();
            if (Operator.PARENTHESIS_LEFT.operator.equals(str)) {
    
    
                System.out.println("缺少右括号! ");
                return null;
            }
            else {
    
    
                list.add(stack.pop());
            }
        }
        return list;
    }

    private String operation(String x, String y, Operator op) {
    
    //操作数运算
        int xisPoint = x.indexOf('.');
        int yisPoint = y.indexOf('.');
        if (xisPoint == -1 && yisPoint == -1) {
    
    //两个整数操作
            if (x.length() < 9 && y.length() < 9) {
    
    //两个不大的整数
                int a = 0;
                int b = 0;
                try {
    
    
                    a = Integer.parseInt(x);
                    b = Integer.parseInt(y);

                } catch (NumberFormatException e) {
    
    
                    System.out.println("操作数非法! ");
                    e.printStackTrace();
                }

                switch (op) {
    
    
                    case ADD:
                        return String.valueOf(a + b);
                    case SUBTRACT:
                        return String.valueOf(a - b);
                    case MULTIPLY:
                        return String.valueOf(a * b);
                    case DIVIDE:
                        double aa = Double.parseDouble(x);
                        double bb = Double.parseDouble(y);
                        if (b == 0) {
    
    
                            System.out.println("进行了除0操作! ");
                            return null;
                        }
                        else {
    
    
                            return String.valueOf(aa / bb);
                        }
                    case EXPONENT:
                        return String.valueOf(Math.pow(a, b));
                    case REMAINDER:
                        return String.valueOf(a % b);
                    default:
                        return null;
                }
            }
            else {
    
    //大整数操作
                BigInteger a = new BigInteger(x);
                BigInteger b = new BigInteger(y);//创建两个大数
                switch (op) {
    
    //大整数仅支持+-*/
                    case ADD:
                        return a.add(b).toString();
                    case SUBTRACT:
                        return a.subtract(b).toString();
                    case MULTIPLY:
                        return a.multiply(b).toString();
                    case DIVIDE:
                        if (b.intValue() == 0) {
    
    
                            System.out.println("进行了除0操作! ");
                            return null;
                        }
                        else {
    
    
                            return a.divide(b).toString();
                        }
                    case EXPONENT:
                        System.out.println("大整数不支持乘方运算");
                        return null;
                    case REMAINDER:
                        System.out.println("大整数不支持求余操作");
                        return null;
                    default:
                        return null;
                }
            }

        }
        else {
    
    //含非整数的操作
            double a = 0.0;
            double b = 0.0;
            try {
    
    
                a = Double.parseDouble(x);
                b = Double.parseDouble(y);
            } catch (NumberFormatException e) {
    
    
                System.out.println("操作数非法! ");
                e.printStackTrace();
            }

            switch (op) {
    
    
                case ADD:
                    return String.valueOf(a + b);
                case SUBTRACT:
                    return String.valueOf(a - b);
                case MULTIPLY:
                    return String.valueOf(a * b);
                case DIVIDE:
                    return String.valueOf(a / b);
                case EXPONENT:
                    return String.valueOf(Math.pow(a, b));
                case REMAINDER:
                    System.out.println("非整数不能进行求余操作");
                    return null;
                default:
                    return null;
            }
        }
    }

    public String calculate(String exp) {
    
    //第3步: 逆波兰表达式运算
        List<String> expList = dealExpr(resolveExpr(exp));//先将运算式转换为逆波兰表达式
        if (expList == null) {
    
    
            return null;
        }
        Stack<String> stack = new Stack<String>();
        for (String str : expList) {
    
    
            Operator op = getOperator(str.substring(0, 1));
            Operand od = getOperand(str.substring(0, 1));
            if (od != null || str.length() > 1) {
    
    //数字直接压栈
                stack.push(str);
            }
            else if (op != null) {
    
    
                String x = "";
                String y = "";
                if (!stack.empty()) {
    
    
                    y = stack.pop();
                }
                if (!stack.empty()) {
    
    
                    x = stack.pop();
                }
                if (!x.isEmpty() && !y.isEmpty()) {
    
    
                    String result = operation(x, y, op);
                    if (result == null) {
    
    
                        return null;
                    }
                    stack.push(result);
                }
                else {
    
    
                    return null;
                }
            }
        }
        return stack.pop();
    }
}

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Cal cal = new Cal();
        Scanner in = new Scanner(System.in);
        String intext = cal.calculate(in.nextLine());
        if (intext != null) {
    
    
            System.out.println(intext);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/zhj12399/article/details/109554417