java實現整數的四則運算,不包括小數和括號

// 枚舉, 對應加減乘除
public enum OperatorEum {
    ADD("+"),
    SUBSTRACT("-"),
    MULTIPY("*"),
    DIVIDE("/");

    private String operatorSign;

    private OperatorEum(String operatorSign) {
        this.operatorSign = operatorSign;
    }

    public String getOperatorSign(){
        return operatorSign;
    }
    public static OperatorEum findOperatorEnum(String operatorSign) {
        for(OperatorEum value : values()) {
            if(value.getOperatorSign().equals(operatorSign)) {
                return value;
            }
        }
        return null;
    }
}

 



import java.util.Arrays;

// 定義一個棧,用來保存用於計算的數字和加減乘除符號
// 主要提供pop, peek, empty, size方法
public class CustomStack<T> {

    private int capacity;

    private int size = 0;

    private static int MAX = 16;

    private Object[] dataArr;

    public CustomStack() {
        this.capacity = MAX;
        dataArr = new Object[this.capacity];
    }

    public CustomStack(int capacity) {
        this.capacity = capacity;
        dataArr = new Object[this.capacity];
    }

    public boolean push(T data) {
        if(dataArr.length == size){
            return false;
        }
        dataArr[size++] = data;
        return true;
    }

    public T pop() {
        T data = (T)dataArr[--size];
        dataArr[size] = null;
        return data;
    }

    public T peek(){
        return (T)dataArr[size-1];
    }

    public boolean empty(){
        return size == 0;
    }

    public int size() { return size;}

    @Override
    public String toString() {
        return "CustomStack{" +
                "dataArr=" + Arrays.toString(dataArr) +
                '}';
    }

    public static void main(String[] args) {


    }
}

 

package test.stack;

import java.util.ArrayList;
import java.util.List;


public class CustomMath {
    // 保存在計算過程要用於計算的數字和臨時計算結果
    private CustomStack<Integer> numberStack;
    // 保存在計算過程中要用於計算的運算符號
    private CustomStack<OperatorEum> operatorStack;

    // 按順序保存數學式子中所有的數字
    private List<Integer> numberList;
    // 按順序保存數學式子中所有的運算符號
    private List<OperatorEum> operatorEumList;

    public CustomMath(){
        numberStack = new CustomStack<>(10);
        operatorStack = new CustomStack<>(10);
        numberList = new ArrayList<>();
        operatorEumList = new ArrayList<>();
    }

    // 正式進行計算
    public Integer calculate(String mathExpression) throws Exception {
        System.out.println("mathExpression: "+mathExpression);
        Integer result = 0;
        if(checkExpression()){
            extractNumberAndOperatorToList(mathExpression);
            int numberSize = numberList.size();
            numberStack.push(numberList.get(0));
            for(int i=1; i<numberSize; i++){
                Integer number = numberList.get(i);
                int j=i-1;

                OperatorEum operatorEum = operatorEumList.get(j);
                if(operatorStack.size() == 0){
                    numberStack.push(number);
                    operatorStack.push(operatorEum);
                }else{
                    OperatorEum storedOperatorEum = operatorStack.peek();
                    if(storedOperatorEum.equals(operatorEum)){
                        Integer number1 = numberStack.pop();
                        Integer number2 = numberStack.pop();
                        result = calculate(number2, number1, operatorStack.pop());
                        numberStack.push(result);
                        numberStack.push(number);
                        operatorStack.push(operatorEum);
                    }else {
                        boolean superior = isSuperiorToStackOperator(storedOperatorEum, operatorEum);
                        if (superior) {
                            result = calculate(numberStack.pop(), number, operatorEum);
                            numberStack.push(result);
                        } else {
                            Integer number1 = numberStack.pop();
                            Integer number2 = numberStack.pop();
                            result = calculate(number2, number1, operatorStack.pop());
                            numberStack.push(result);
                            numberStack.push(number);
                            operatorStack.push(operatorEum);
                        }
                    }
                }
            }
        }else{
           throw new Exception("Illegal math expression");
        }
        while (numberStack.size() > 1){
            Integer number1 = numberStack.pop();
            Integer number2 = numberStack.pop();
            result = calculate(number2,number1, operatorStack.pop());
            numberStack.push(result);
        }
        return numberStack.pop();
    }

    // 具體的某種計算, 思路 number1 運算符號 number2, 兩個參數的位置很重要,決定了
    // 在計算式了中的位置,直接影響計算結果,比如3-2與2-3,
    private Integer calculate(Integer number1, Integer number2, OperatorEum operatorEum){
        Integer result = 0;
        switch (operatorEum) {
            case ADD:
                result = number1+number2;
                break;
            case SUBSTRACT:
                result =  number1-number2;
                break;
            case MULTIPY:
                result =  number1*number2;
                break;
            case DIVIDE:
                result =  number1/number2;
                break;
        }
        return result;
    }

    // 將數學式子中的數字和運算符號按順序保存到對應的List中
    private void extractNumberAndOperatorToList(String mathExpression){

        String numberStr = "";
        int length = mathExpression.length();
        for(int i=0; i<length; i++){
            char ch = mathExpression.charAt(i);
            OperatorEum operatorEum = OperatorEum.findOperatorEnum(String.valueOf(ch));
            if(operatorEum == null) {
                numberStr += ch;
            }else{
                this.numberList.add(Integer.valueOf(numberStr));
                numberStr = "";
                this.operatorEumList.add(operatorEum);
            }
        }
        this.numberList.add(Integer.valueOf(numberStr));
    }
    // 一般性的校驗,檢查一下輸入的數學式子是否合未能
    private boolean checkExpression(){
        return true;
    }
    // 比較後一個運算符號的級別是否高於前一個運算符號,參數的位置很重要,
    // 前一個運算符號要作爲第一個參數, 後一個運算符號要作爲第二個參數
    private boolean isSuperiorToStackOperator(OperatorEum operatorEum1, OperatorEum operatorEum2){
        String stackOperator = operatorEum1.getOperatorSign();
        String operator = operatorEum2.getOperatorSign();
        boolean highPriority = operator.equals("*") || operator.equals("/");
        boolean lowPriority = stackOperator.equals("+") || stackOperator.equals("-");
        return highPriority && lowPriority;
    }

    // 進行測試
    public static void main(String[] args) {
        String expression = "0-1/1+2*2/2-1";  //
        CustomMath customMath = new CustomMath();
        try {
            Integer result = customMath.calculate(expression);
            System.out.println(result);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }

    }
}

核心思路講解:

1. numberStack中只保存兩個數字, operatorStack中只保存一個運算符號,這樣兩個棧中數據合起來就是一個完整的數學表達式: a+b,兩個棧中的數據一直維持這種狀態。  2.初次入棧。在第一次執行numberList的遍歷前,先在numberStack中放入一個數字numberStack.push(numberList.get(0)),然後從1開始遍歷。經過下面步驟,兩個棧中的數據滿足了第1點要求。

if(operatorStack.size() == 0){
    numberStack.push(number);
    operatorStack.push(operatorEum);
} 

3. 遍歷計算及入棧講解,看代碼按思路分析。

// storedOperatorEum爲符號棧中保存的運算符號, operatorEum爲從符號list取出的運算符號
// number是從數字list中取出的數字,將用來計算或是入棧
OperatorEum storedOperatorEum = operatorStack.peek();
if(storedOperatorEum.equals(operatorEum)){
//如果運算符號相同,先將棧中數字和運算符號彈出並進行計算,將計算結果入棧保存,再將number入棧保存,
// 將operatorEum入棧保存
    Integer number1 = numberStack.pop();
    Integer number2 = numberStack.pop();
// 此處要注意,一定是第二次彈出的數字作爲第一個運算數字,第一次彈出的數字作爲第二個運算數字
// 因爲3-2與2-3的結果就完全不同
    result = calculate(number2, number1, operatorStack.pop());
    numberStack.push(result);
    numberStack.push(number);
    operatorStack.push(operatorEum);
}else {
    boolean superior = isSuperiorToStackOperator(storedOperatorEum, operatorEum);
    if (superior) {
        // operatorEum的級別高於棧中運算符號的級別,就要數字棧中頂元素與number進行運算
// 將計算結果入棧。 要注意的是數字棧中的頂元素要作爲第一個運算數字, number是作爲第二個
// 此時,operatorEum與number都完成了計算,所以不需要入棧了
        result = calculate(numberStack.pop(), number, operatorEum);
        numberStack.push(result);
    } else {
// 如果operatorEum的級別與棧中運算符號的級別相等,則將棧中數字和運算符號彈出並進行計算,將計算// 結果入棧保存。
// 然後number與operatorEum要進行入棧
        Integer number1 = numberStack.pop();
        Integer number2 = numberStack.pop();
        result = calculate(number2, number1, operatorStack.pop());
        numberStack.push(result);
        numberStack.push(number);
        operatorStack.push(operatorEum);
    }
}

 

發佈了39 篇原創文章 · 獲贊 9 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章