1. 程式人生 > 其它 >解決double型別資料四則運算精度丟失問題

解決double型別資料四則運算精度丟失問題

技術標籤:程式碼

直接對double型別的資料進行計算,很容易發生精度丟失問題
在這裡插入圖片描述
使用BigDecimal類計算,可以避免精度丟失

 				//Double num2 = Double.parseDouble(numStack.pop());
                //Double num1 = Double.parseDouble(numStack.pop());
            	BigDecimal num2 = new BigDecimal(numStack.pop());
            	BigDecimal num1 = new BigDecimal(
numStack.pop()); if(arrays[i].equals("+")){ BigDecimal result = num1.add(num2); numStack.push(result.toString()); } else if(arrays[i].equals("-")){ BigDecimal result = num1.subtract
(num2); numStack.push(result.toString()); } else if(arrays[i].equals("*")){ BigDecimal result = num1.multiply(num2); numStack.push(result.toString()); } else if(arrays[i]
.equals("/")){ BigDecimal result = num1.divide(num2); numStack.push(result.toString()); }

為了完成多個數據的組合運算,這裡使用棧對運算子和運算數進行管理


設計一個存放字串物件的棧類

public class Stack {
    private ArrayList<String> stack = new ArrayList<>();

    public boolean isEmpty(){
        return stack.size() == 0;
    }
    public int getSize(){
        return stack.size();
    }
    public String peek(){
        if(!isEmpty()) {
            return stack.get(stack.size() -1 );
        }
        else {
            return "false";
        }
    }
    public String pop(){
        if(!isEmpty()){
            String top = stack.get(stack.size() - 1);
            stack.remove(stack.size() - 1);
            return top;
        }
        else{
            return "false";
        }
    }
    public void push(String o){
        stack.add(o);
    }
    @Override
    public String toString(){
        return "Stack:" + stack.toString();
    }
}

計算類

public class Compute {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        String str = input.nextLine();

        String[] inOrderArrays = strToArrays(str);
        System.out.println(Arrays.toString(inOrderArrays));
        String[] postOrderArrays = toPostOrder(inOrderArrays);
        System.out.println(Arrays.toString(inOrderArrays));
        BigDecimal result = toCompute(postOrderArrays);
        System.out.println(result);
    }
    /*
    將字串分割成運算元和操作符的字串陣列
    */
    public  static String[] strToArrays(String str){
        int strLength = str.length();
        int beginIndex = 0; int endIndex = 0;
        String[] Arrays = new String[strLength];
        int arraysIndex = 0;

        for(int i = 0; i < strLength; i++){
            if(str.charAt(i)=='*'||str.charAt(i)=='/'||str.charAt(i)=='+'||str.charAt(i)=='-'||str.charAt(i)=='('||str.charAt(i)==')'){
                endIndex = i -1 ;
                if(beginIndex <= endIndex ){
                    Arrays[arraysIndex] = str.substring(beginIndex, endIndex+1);
                    Arrays[arraysIndex + 1] = String.valueOf(str.charAt(i));
                    arraysIndex += 2;
                    beginIndex = i + 1;
                }
                else{
                    Arrays[arraysIndex] = String.valueOf(str.charAt(i));
                    arraysIndex += 1;
                    beginIndex = i + 1;
                }
            }
        }
        Arrays[arraysIndex] = str.substring(beginIndex, str.length());
        String[] Arrays2 = new String[arraysIndex+1];
        for(int i = 0; i < arraysIndex+1; i++) {
            Arrays2[i] = Arrays[i];
        }
        return Arrays2;
    }
    /*
    將中綴表示式轉為字尾表示式,返回的是字串陣列
    */
    public static String[] toPostOrder(String[] arrays){
        /*規則:
        *1,運算數直接輸出
        *2,左括號壓入堆疊
        *3,右括號 將棧頂的運算子彈出並輸出,括號出棧不輸出
        *4,運算子:
        *    若優先順序大於棧頂運算子,壓入棧
        *    若優先順序小於或等於棧頂運算子,棧頂運算子彈出並輸出,
        *       繼續和新棧頂比較,直到比棧頂運算子優先順序大,將它壓入棧
        *5,物件處理完畢後,將棧中運算子彈出並輸出
        */
        Stack operStack = new Stack();//建立了一個操作符的棧
        int arraysLength = arrays.length;
        String[] arrays2 = new String[arraysLength];//輸出後的字元陣列
        int tempIndex = 0;

        //將字串陣列遍歷
        for(int i = 0; i < arraysLength; i++){
            //操作符入棧
            if(isOper(arrays[i])){
                //棧為空時直接入棧
                if(operStack.isEmpty()){
                    operStack.push(arrays[i]);
                }
                else{
                    //操作符為"("時直接入棧
                    if( arrays[i].equals("(")  ){
                        operStack.push(arrays[i]);
                    }
                    //操作符為")"時棧頂出棧並輸出,直到遇到"(", "("出棧,")"不入棧
                    else if( arrays[i].equals(")") ){
                        while(operStack.peek().equals("(") == false ){
                            arrays2[tempIndex] = operStack.pop();
                            tempIndex += 1;
                        }
                        operStack.pop();//"("出棧
                    }
                    //其他操作符需要比較與棧頂的優先順序
                    else{
                        //棧頂是"(", 直接入棧
                        if(operStack.peek().equals("(") ){
                            operStack.push(arrays[i]);
                        }
                        else{
                            //優先順序高,直接入棧
                            if(getPriority(arrays[i].charAt(0)) > getPriority(operStack.peek().charAt(0))
                                && operStack.isEmpty() == false ){
                                operStack.push(arrays[i]);
                            }
                            //優先順序低或者相等,棧頂出棧並輸出,直到優先順序比棧頂高
                            else{
                                while(getPriority(arrays[i].charAt(0)) <= getPriority(operStack.peek().charAt(0))
                                        && operStack.isEmpty() == false){
                                    arrays2[tempIndex] = operStack.pop();
                                    tempIndex += 1;
                                    //若棧頂全部彈出,則直接入棧
                                    if(operStack.isEmpty()) {
                                        operStack.push(arrays[i]);
                                        break;
                                    }
                                }
                                if(getPriority(arrays[i].charAt(0)) > getPriority(operStack.peek().charAt(0))){
                                    operStack.push(arrays[i]);
                                }
                            }
                        }
                    }
                }
            }
            //運算元直接新增到 字串陣列2
            else if(isNum(arrays[i])){
                arrays2[tempIndex] = arrays[i];
                tempIndex += 1;
            }
            else{
            }
        }
        while(!operStack.isEmpty()){
            arrays2[tempIndex] = operStack.pop();
            tempIndex += 1;
        }
        String[] arrays3 = new String[tempIndex];
        for(int i = 0; i < tempIndex ;i++){
            arrays3[i] = arrays2[i];
        }
        return arrays3;
    }
    /*
    得到操作符的優先順序
    */
    public static int getPriority(char c){
        if(c == '*' || c == '/'){
            return 2;
        }
        else if (c == '+' || c == '-'){
            return 1;
        }
        else{
            return 999;
        }
    }
    /*
    由字尾表示式計算得值
    */
    public static BigDecimal toCompute(String[] arrays){
        /*規則:
        *中綴表示式不用比較優先順序
        *將運算數入棧,每讀到一個運算子
        *就彈出棧頂的兩個運算數,運算完畢後將結果壓入棧
        */
        Stack numStack = new Stack();//建立了一個運算元的棧
        int arraysLength = arrays.length;
        //遍歷字尾表示式的字串陣列
        for(int i = 0; i < arraysLength; i++){
            if(isNum(arrays[i])){
                numStack.push(arrays[i]);
            }
            else if(isOper(arrays[i])){
                //Double num2 = Double.parseDouble(numStack.pop());
                //Double num1 = Double.parseDouble(numStack.pop());
            	BigDecimal num2 = new BigDecimal(numStack.pop());
            	BigDecimal num1 = new BigDecimal(numStack.pop());
                if(arrays[i].equals("+")){
                    BigDecimal result = num1.add(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("-")){
                	BigDecimal result = num1.subtract(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("*")){
                	BigDecimal result = num1.multiply(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("/")){
                	BigDecimal result = num1.divide(num2);
                    numStack.push(result.toString());
                }
                else{
                }
            }
            else{
            }
        }
        //Double result = Double.parseDouble(numStack.pop());
        BigDecimal result = new BigDecimal(numStack.pop());
        return result;
    }
    /*
    判斷該字串是否為操作符
    */
    public static boolean isOper(String str){
        if(str.equals("*")||str.equals("/")||
            str.equals("+")||str.equals("-")||
            str.equals("(")||str.equals(")")){
                return true;
            }
        else{
            return false;
        }
    }
    /*
    判斷該字串是否為運算元
    */
    public static boolean isNum(String str){
        if(str.equals("*")||str.equals("/")||
            str.equals("+")||str.equals("-")||
            str.equals("(")||str.equals(")")){
                return false;
            }
        else{
            return true;
        }
    }
}

在這裡插入圖片描述